[] At the front end of the front end using the mathematical function knowledge + box-shadow waves graphics solution CSS techniques one - draw curves using trigonometric functions in CSS graphics and animation show

sequence

Today is a mathematical function related topics brush, brush to the following article, wow oh ~ interesting. Using the sin and cos of complex curves. Portal below.

CSS techniques one - plotted graphics and animations showing the use of trigonometric functions in CSS

I happened to review some mathematical knowledge, then a handful of hands-on practice in the use of mathematical functions using css draw a continuous curve.

 

Function: Step

In mathematics, the function refers to a group of the domain by a set of expressions , mapped to a set range, that is to say the function f (x) = x ^ 2 denotes a set, each input x, x ^ 2 is fixed by returns a value of y, the definition can be obtained thereby:

When the set X = {-2, -1, 0, 1, 2} is input to the function f, to give the range set Y = {y | y> = 0}.  

We can also list format, a more intuitive lists the value of the function:

When x = 1 y = 1

When x = 2 y is equal to 4

x= -2 -1 0 1 2 ...
y = 4 1 0 1 4 ...

From this table, we can draw on the axis y = f (x) = x ^ 2 like the function:

Opening control

If we y = x ^ 2 plus minus sign what will happen, the y-= f (the X-) = - (the X-^ 2)

? The image will become like upside down like n?

 In this way, we can use this function, to give two curves, the positive u and anti n- . So the question is , to draw an arbitrary curve, it means that the curve should be large or small, can be any position in the figure, to how to do it?

 

Ah Think about it, if the function f (x) = x ^ 2 and then let it divide -2

f(x) = x^2 / -2

x= -2 -1 0 1 2 ...
y = -2 -1/2 0 -1 /2 -2 ...

Hand-animated look so long about the following image:

 

 

 

is divided by 2 because y becomes smaller (the value of y imagine sides becomes smaller), when x = 2, y will be equal to 2, this results in a graph widened.

Then we can know if replaced by f (x) = x ^ 2 * 2, when x = 2, y equals 4, the curve would be narrower.

If divided by the number into a negative number, the opening will be down .

From the above we can obtain a size of the opening may be a function of the control curve

 

May be converted to f (x) = x ^ 2 / t when t is greater than 0, curve upwardly open, t is less than 0, the curve opening downwards

The yaw control

Now we can control the size of the opening, so how about control curve and move around it?

P offset is assumed that the left and right

Provided the function f (x) = (x - P) ^ 2, P = 1 yields the following table:

x= -2 - 1 -1 - 1 - 1 - 1 - 1 3 - 1
y = 9 4 1 0 1 4

Or image, probably a long way:

 

 

It can be seen about the influence on the image value P offset

Vertical offset control

Shift down control, in fact, the control function f (x) = x ^ 2 the size of the value of y, just to f (x) = x ^ 2 - H it can control the vertical

Vertical offset is assumed that H

Provided the function f (x) = x ^ 2 + H, H = 1 to obtain the following table:

x= -2  -1 



...
y = 5 2 1 2 4 ...

图就不画啦,可以直接看到x=0时,顶点已经不再0上了,向上偏移了1位

 

值域区间和宽度的关系

什么是区间

集合的语言,我们定义各种区间为:
说人话就是有两种区间 开区间 与 闭区间
开区间不包含0,闭区间包含0
 
区间和宽度的关系
 
我们要一个完整的半圆|半弧,那么必须要定义一个起始x和结束x,否则曲线就是无限延伸的没有意义
 
我们从函数f(x) = x^2的图像上任意取最小x a 和最大x b,b - a就是x的定义区间,也就是函数f(x) = x^2的定义域:

 

 

好了,理解了上面的东西,万事俱备,接下来就是更复杂一点的问题了!

 

接下来,工程问题,曲线

目标,使用函数

 

 

实现开头引用文章中,利用 cos和sin实现的曲线。

分析

通过上面对函数的分析我们可以得到一个式子:

设 抛物线开口 = T

设 左右偏移 = P

设 上下偏移 = H

设 定义域 = [a, b] (开区间a到开区间b)

函数 f(x) = (x - P) ^ 2 / T - H, T > 0 开口向上

函数g(x) = (x - P) ^ 2 / (T) - H, T < 0 开口向下

 

现在我们要使弧线A的结束点是弧线B的起始点,并且调换方向,那么:

 

 

如图的推理过程,首先反转A,将A向下移动H,再向左移动P,得到一个新的弧度,以此类推递归:

然后用js实现一个简单的算法如下:

 // g(x) = f(x-(b-a)) - 2* f(a), T < 0
     function g (x, T, P, range) {
            const [a, b] = range
            return f(x - (b - a), T, P, range) - 2 * f(0, T, P, range)
        }

     // 当 T < 0 相当于上面图中的 p(x) = (x - (- (T / B * f(b - a))))  / T, T < 0 
        // 当 T > 0 直接计算 f(x) = (x - P) ^ 2 / T, T > 0
        function f (x, T, P, range, s) {
            const [a, b] = range
            if (T < 0 && !s) {
                return Math.pow(x - (-(T / b * f(b - a, T, P, range, true))), 2) / T
            }
            if (T > 0 || s) {
                return Math.pow(x - P, 2) / T
            }
            
        }
        // 选择初始函数
        function getY (x, T, P, range) {
            if (T > 0) {
                return f(x, T, P, range)
            } else {
                return g(x, T, P, range)
            }
        }
        //获取一堆x,y点组成的集合, size = 波浪数量,origin=原点,item = 配置P H T变量,points和ysize为递归存储数据
        function GetPoints(size, origin, item, points = [], ysize) {
            if (ysize === undefined) {
                ysize = size
            }
            if (size <= 0) {
                return points
            }
            const z = size % 2 === 0
            const M = 1 // 密度
            const width = item.b - item.a // 宽度
            let i = width;  
            while (i >= -width) {
                const point = [
                    (origin[0] + i) + (ysize - size) * (width * 2), // x
                    origin[1] + getY(i, (z ? item.T : -item.T), item.P, [ // y
                        item.a,
                        item.b
                    ])
                ]
                points.push(point)
                i -= M;
            }
            GetPoints(size-1, origin, {
                a: item.a,
                b: item.b,
                T: item.T,
                P: item.P
            }, points, ysize)
            return points;
        }

 

效果

通过一连串懵逼式的计算和换算,我们有了一个可以获取固定数量相连的曲线,通过T控制开口,P控制x偏移,定义域[a,b]控制宽度,我们来实现骚操作:

 拉到本地跑一跑:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .circle {
            position: absolute;
            width: 1px;
            height: 1px;
            background: #333;
            border-radius: 50%;
            left: 0px;
            top: 0px;
            transition: all 200ms;
        }
    </style>
</head>
<body>
    <div class="circle" id="circle"></div>
    <script>
        function g (x, T, P, range) {
            const [a, b] = range
            return f(x - (b - a), T, P, range) - 2 * f(0, T, P, range)
        }

        function f (x, T, P, range, s) {
            const [a, b] = range
            if (T < 0 && !s) {
                return Math.pow(x - (-(T / b * f(b - a, T, P, range, true))), 2) / T
            }
            if (T > 0 || s) {
                return Math.pow(x - P, 2) / T
            }
            
        }

        function getY (x, T, P, range) {
            if (T > 0) {
                return f(x, T, P, range)
            } else {
                return g(x, T, P, range)
            }
        }
        function GetPoints(size, origin, item, points = [], ysize) {
            if (ysize === undefined) {
                ysize = size
            }
            if (size <= 0) {
                return points
            }
            const z = size % 2 === 0
            const M = 1 // 密度
            const width = item.b - item.a // 宽度
            let i = width;  
            while (i >= -width) {
                const point = [
                    (origin[0] + i) + (ysize - size) * (width * 2), // x
                    origin[1] + getY(i, (z ? item.T : -item.T), item.P, [ // y
                        item.a,
                        item.b
                    ])
                ]
                points.push(point)
                i -= M;
            }
            GetPoints(size-1, origin, {
                a: item.a,
                b: item.b,
                T: item.T,
                P: item.P
            }, points, ysize)
            return points;
        }

        /**
         * 生成box-shadow参数
         */
        function getBoxShadow (color = '#333') {
            let points = GetPoints(6, [500, 100], {
                    a : 0,
                    b : 100,
                    T : 200,
                    P : 0
                })
            
            // const s = []
            const s = points.map((point) => `${point[0]}px ${point[1]}px 0 0 ${color}`)
            return s.join(',')
        }

        document.querySelector('#circle').style.cssText = `box-shadow: ${getBoxShadow()}; transform: rotate(90deg) translate(-500px, -500px)`

    </script>
</body>
</html>

 

一毛一样,大功告成。

 

 

展望

利用数学函数,我们也可以画出使用sin / cos一毛一样的曲线,更多的,我们也可以用它来描绘一个物体的运动动作,例如波浪运动,抛物线运动。

甚至可以用css画苦逼脸:

 

 

加点动画玩玩

 

延续

数学与编程,有时候真的是相依相承的东西。从工程的角度来说,数学和程序算法有非常重要的关系,推荐大家阅读《数学与泛型编程》(高效编程的奥秘),受益匪浅,感觉整个程序职业生涯有了一次很棒的升华!

完。

 

Guess you like

Origin www.cnblogs.com/ztfjs/p/frontmath.html