html中三角函数表示什么,【前端】 在前端利用数学函数知识+box-shadow解波浪图形...

今天正在刷数学函数相关题目,刷到了下面这篇文章,哇哦~有意思。 利用cos和sin实现复杂的曲线。传送门在下面。

正巧在复习一些数学知识,遂动手实践了一把使用 数学中的函数  使用css画连续曲线。

函数: 第一步

在数学中 函数是指,一组定义域通过一组表达式, 映射到一组值域,也就是说 函数 f(x) = x^2表示一个集合,每个输入x,固定通过x^2返回一个值y,由此定义可得:

当集合 X = {-2, -1, 0, 1, 2}  输入到函数f,得到的值域集合 Y = { y | y >= 0 }。

我们也可以通过列表格,更直观的列举出函数的值:

当x = 1 时 y等于 1

当x = 2时 y等于 4

x=

-2

-1

0

1

2

...

y=

4

1

0

1

4

...

由这个表格,我们可以在坐标轴画出关于y = f(x) = x^2的函数的样子:

f6ade53999b2005de81e7b23ef1cd7d0.png

开口控制

如果我们在y = x^2 加个负号会怎么样呢,y = f(x) = -(x ^ 2)

图像会倒过来变成像 n 这样的样子?

就这样,我们可以通过这个函数,得到两种曲线,正的u 和 反的n。那么问题来了,要画任意曲线,那么意味着,曲线要可大可小,可以在图中的任意一个位置,要怎么办呢?

嗯 仔细想想,如果函数 f(x) = x^2 再让它除以-2呢

f(x) = x^2 / -2

x=

-2

-1

0

1

2

...

y=

-2

-1/2

0

-1 /2

-2

...

手动画一下图像大约长下面这样:

740cfa8954508c1eb42983f861fd8424.png

y会因为除以2变得更小(想象一下两侧的y值会变小),当x = 2 ,  y就会等于2, 这样的结果是曲线变宽。

那么我们也可以知道 如果 换成 f(x) = x^2 * 2, 当x=2,y等于4,曲线会变窄。

如果除以的数变成了负数,开口就会向下。

由上面我们可以得到一个可以控制曲线开口大小的函数

也可以换算到 f(x) = x^2 / t 当t 大于0,曲线开口向上,t小于0,曲线开口向下

左右偏移控制

现在我们可以控制开口大小,那么怎么样控制曲线左右移动呢?

假设左右偏移量是P

设函数 f(x) = (x - P)^2,P = 1 得到下面的表格:

x=

-2 - 1

-1 - 1

0 - 1

1 - 1

2 - 1

3 - 1

y=

9

4

1

0

1

4

还是用图像,大概长这样:

01ca6eebb048dc5878252381979a68a4.png

可以看到,P的取值影响图像的左右偏移

上下偏移控制

控制上下偏移,实际上就是控制函数 f(x) = x ^2的值y的大小,只需要将   f(x) = x ^2 - H  就可以控制上下啦

假设上下偏移量是H

设函数 f(x) = x^2 + H,H = 1 得到下面的表格:

x=

-2

-1

0

1

2

...

y=

5

2

1

2

4

...

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

值域区间和宽度的关系

什么是区间

用集合的语言,我们定义各种区间为:

f2deb48f8c5494ee809f18b82ff5e0fe98257ed5.jpg

21a4462309f79052818a509f0ef3d7ca7acbd5fd.jpg

a9d3fd1f4134970aa1da078e97cad1c8a6865de1.jpg

c75c10385343fbf28d60b182b27eca8064388fc6.jpg

说人话就是有两种区间 开区间 与 闭区间

开区间不包含0,闭区间包含0

区间和宽度的关系

我们要一个完整的半圆|半弧,那么必须要定义一个起始x和结束x,否则曲线就是无限延伸的没有意义

我们从函数f(x) = x^2的图像上任意取最小x a 和最大x b,b - a就是x的定义区间,也就是函数f(x) = x^2的定义域:

23cad54cbb3d63efa4b79cb44606ca6c.png

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

接下来,工程问题,曲线

目标,使用函数

c3c6573e85945be132a0186bf7d24751.png

实现开头引用文章中,利用 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的起始点,并且调换方向,那么:

a84011fbe5ab264019ec38f8beda9532.png

如图的推理过程,首先反转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]控制宽度,我们来实现骚操作:

c3c6573e85945be132a0186bf7d24751.png

拉到本地跑一跑:

Document

.circle {

position: absolute;

width: 1px;

height: 1px;

background: #333;

border-radius: 50%;

left: 0px;

top: 0px;

transition: all 200ms;

}

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)`

一毛一样,大功告成。

3933aa99c167d8208cdecbca420cae05.png

展望

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

甚至可以用css画苦逼脸:

17f2bfd52ea6be75841881dc8a0417d6.png

加点动画玩玩

998a50f355e68c8a31225fae9440fed9.png

延续

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

完。

标签:box,return,函数,前端,ysize,item,range,shadow,size

来源: https://www.cnblogs.com/ztfjs/p/frontmath.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值