基于 function-plot.js 开源库绘制数学函数图像实现兼文档翻译

一、前言:

前段时间移动项目想实现一个能实时绘制数学函数图像的H5小应用, app 通过 webview 进行嵌入,目前网上提供了大致有两种方法:

①、Chart.js 结合 Plugins 绘制 ===> https://www.bianchengquan.com/article/475747.html

②、原生 JavaScript + canvas 计算描点绘制 ===> https://blog.csdn.net/weixin_30341745/article/details/94964723


经过测试这两个方法应对一些复杂的函数图像绘制显得捉襟见肘,那么有没有什么库或者框架专门是用来绘制数学函数呢?经过多方资料查找,发现了 function-plot.js 这款强大的数学函数绘制库:

Function Plot 是一个建立在 D3.js 之上的强大库,其目的是用很少的配置来渲染数学函数图像。该库目前支持交互式折线图和散点图,每当修改坐标系比例时,都会使用新边界再次动态绘制函数!

在这里插入图片描述
就在我决定使用这个库来实现我的需求时,为了不想花时间去看英文文档,想着直接百度找个demo来快速入门,却发现网上对 function-plot.js 库的介绍与使用甚少,都是最最基础的属性使用,无法满足我的要求。经过几个小时的英文开发文档学习,最终实现了想要的效果。对官方文档绘制方法属性进行翻译,帮助码友降低学习成本。

官方文档https://mauriciopoppe.github.io/function-plot/docs/globals.html


二、效果展示:

在这里插入图片描述

体验地址http://124.223.70.170:8080/function-draw/index.html#/
开源地址https://gitee.com/xxwproject/function-draw

基本可以实现各种复杂函数的绘制,体验前建议先看下使用说明,由于是 uniapp 编写的 H5 项目,浏览器访问时,请 F12 转化为移动端模式, 然后刷新一下再使用。


三、function-plot.js 使用说明:

1、引入 function-plot.js 库 (version: >= 1.22.8)

npm i function-plot

2、基础使用:(uniapp h5 项目)

申请一个 x, y 轴正负范围为 [-8,8] 区间的坐标图,然后画出 x^2 的图像,鼠标触摸函数线上的某一点实时求该点的切线。

<template>
	<view class="content">
		<div id="root"></div>
	</view>
</template>

<script>
	import functionPlot from 'function-plot';
	export default {
		data() {
			return {}
		},
		mounted() {
			this.draw()
		},
		methods: {
			draw() {
			    // 依据  body 边距动态定义画布长宽
				let contentsBounds = document.body.getBoundingClientRect();
				let width = 800;
				let height = 500;
				let ratio = contentsBounds.width / width;
				width *= ratio;
				height *= ratio;
				// 画图核心如下
				functionPlot({
					target: "#root",  // 目标画布节点
					// 定义画布长宽
					width,
					height,
					// 设置 x,y 轴默认区间
					xAxis: {domain: [-8, 8], label: 'x 轴'},
					yAxis: {domain: [-8, 8], label: 'y 轴'},
					// 显示方格
					grid: true,
					// 需要绘制的函数,是数组,所以可以绘制多条函数
					data: [{
						fn: "x^2", // 也可以 pow(x, 2)
					  // 画出某点的切线 (没啥用,建议删除)
						derivative: {
							fn: "2 * x",
							updateOnMouseMove: true
						}
					}]
				});
			}
		}
	};
</script>

<style>
	.<!--uniapp 默认样式,省略-->
</style>

在这里插入图片描述


四、FunctionPlot({}) 核心绘制方法的属性介绍:

在这里插入图片描述

属性名属性含义
annotations作平行线标注
title给画布命名
target目标 html 节点,用于生成画布
width画布默认宽度设置
height画布默认长度设置
xAxisx轴相关设置
yAxisy轴相关设置
disableZoom是否可以手动伸缩画布
grid是否显示单元格
id内置私有属性,标识,无需关注
plugins插件配置(很少使用)
tip设置触摸函数某点时进行x,y 轴虚线绘制以及x,y 值计算结果显示
xDomain用于在多次调用 functionPlot 时保留 x 域的内部状态
yDomain用于在多次调用 functionPlot 时保留 y 域的内部状态
data需要绘制的函数

五、属性参数详细使用:

一、绘制函数曲线

最短的示例,函数 y = x 2 y = x^2 y=x2 使用画布大小定义的范围内的值进行评估绘制(默认尺寸为 550x350)
所需的参数是:
target 请看 二、 中表格对应属性解释
data 一个对象数组,其中包含有关要呈现的函数的信息
data.fn (string) 要渲染的数学表达式,使用区间算术对其进行解析和评估绘制
表示数学表达式的字符串的语法就像 ECMAScript 一样,但是 ^ 运算符会被替换成 pow

functionPlot({
  target: '#quadratic',
  data: [{
    fn: 'x^2'
  }]
})

在这里插入图片描述


二、附加属性选项

上图还可以在 functionPlot({}) 里定义以下附加基础选项:
title: 请看 二、 中表格对应属性解释
width: 请看 二、 中表格对应属性解释
height:请看 二、 中表格对应属性解释
xAxis: 请看 二、 中表格对应属性解释
type: 此轴的刻度类型,可能值线性|对数(默认值:‘线性’)
label: x 轴标签
domain: x 轴左右边界默认值
yAxis: 同 xAxis
disableZoom:请看 二、 中表格对应属性解释

functionPlot({
  title: 'y = x * x',
  target: '#quadratic-with-options',
  width: 580,
  height: 400,
  disableZoom: true,
  xAxis: {
    label: 'x - axis',
    domain: [-6, 6]
  },
  yAxis: {
    label: 'y - axis'
  },
  data: [{
    fn: 'x^2'
  }]
})

在这里插入图片描述


三、画布添加网格

设置 grid: true 到 functionplot({}) 选项中

functionPlot({
  target: '#grid',
  xAxis: {
    label: 'real'
  },
  yAxis: {
    label: 'imaginary'
  },
  grid: true,
  data: [
    { fn: 'sqrt(1 - x * x)' },
    { fn: '-sqrt(1 - x * x)' }
  ]
})

在这里插入图片描述


四、区间样本数

nSamples 确定函数将在当前域中评估的等距点的数量,增加它将更准确地使用矩形表示函数,但是太大会影响处理绘制速度(一般此参数忽略不使用)

functionPlot({
  target: '#samples',
  data: [{
    fn: 'sin(x)',
    nSamples: 100
  }]
})

在这里插入图片描述


五、annotations 标注选项使用

可以在 annotations 选项中设置与 y 轴或 x 轴的平行线:
x:平行于y轴的直线的x坐标
y:平行于x轴的直线的y坐标
text(可选)显示在平行线旁边的注释
注意:需要在对象上设置 x 或 y,同时设置它们会引发异常

functionPlot({
  target: '#annotations',
  yAxis: {domain: [-1, 9]},
  data: [{
    fn: 'x^2'
  }],
  annotations: [{
    x: -1
  }, {
    x: 1,
    text: 'x = 1'
  }, {
    y: 2,
    text: 'y = 2'
  }]
})

在这里插入图片描述


六、绘制区间范围与区域图

如果未设置 range 区间范围,closed: true 时,函数区域图将取自当前x轴的正负边界。
range: 一个 2 位数的数组,该函数将仅在此范围内绘制
closed:true 将渲染闭合路径区域图,y0 将始终为 0,y1 将为 f n ( x ) fn(x) fn(x)

functionPlot({
  target: '#closed',
  xAxis: {domain: [-2, 12]},
  data: [{
    fn: '1+2sin(x)',
    range: [2, 8],
    closed: true
  }]
})

在这里插入图片描述


七、 对数刻度

对数刻度(log scale)是当数据的值在一个很大范围内时,利用对数使此降低到一个更加易处理的范围。通过在 xAxis 选项中指定要记录的轴类型,可以将每个轴的类型配置为对数,请注意此更改如何影响函数的采样方式

var instance = functionPlot({
  target: '#logarithmic',
  xAxis: {
    type: 'log',
    domain: [0.01, 1]
  },
  yAxis: {
    domain: [-100, 100]
  },
  grid: true,
  data: [{
    fn: '1/x * cos(1/x)',
    // 让它看起来像一个定积分
    closed: true
  }]
})

在这里插入图片描述


八、多个函数图像绘制

上面例子中看到的data是一个数组,这意味着可以在同一个画布中绘制多个函数

functionPlot({
  target: '#multiple',
  data: [
    { fn: 'x', color: 'pink' },
    { fn: '-x' },
    { fn: 'x * x' },
    { fn: 'x * x * x' },
    { fn: 'x * x * x * x' }
  ]
})

在这里插入图片描述


九、函数图像绘制类型

在 function-plot 中表示函数的三种方式:
polyline: 使用内置的采样器来渲染一组不相交的线条
scatter: 虚线
interval: 使用区间算术采样器来渲染一组不相交的矩形
在选项 graphType 中设置要渲染的图形类型(默认为间隔)

functionPlot({
  target: '#graph-types',
  data: [{
    fn: '-sqrt(-x)',
    nSamples: 100,
    graphType: 'scatter'
  }, {
    fn: 'sqrt(x)',
    graphType: 'polyline'
  }, {
    fn: 'x^2',
    graphType: 'interval'
  }]
})

在这里插入图片描述


十、鼠标坐标位置提示

鼠标的坐标位置出现小圆圈称为“提示”,可以配置以下选项:
xLine: true 以在尖端位置显示平行于 y = 0 y = 0 y=0 的虚线
yLine: true 以在尖端位置显示平行于 x = 0 x = 0 x=0 的虚线
renderer: 提示中显示的文本的自定义渲染函数
注意:提示仅适用于线性函数
当您不希望函数有提示时,请将 skipTip: true 属性添加到保存要呈现的函数信息的对象

functionPlot({
  target: '#tip',
  tip: {
    xLine: true,    // dashed line parallel to y = 0
    yLine: true,    // dashed line parallel to x = 0
    renderer: function (x, y, index) {
      // the returning value will be shown in the tip
    }
  },
  yDomain: [-1, 9],
  data: [
    { fn: 'x^2' },
    {
      fn: 'x',
      skipTip: true
    }
  ]
})

在这里插入图片描述


十一、nth-root:x 的 a/b 次方 (x^2/3)

绘制根可能是一个具有挑战性的问题,大多数人实际上会绘制 x a b x^{\tfrac{a}{b}} xba 类型的表达式,特别是他们会分析指数的分母(在负 x 轴上绘图)、可以使用 nthRoot 函数来解决这些问题

博主当初想绘制 x的 2/3 次方,发现无法使用 x^(2/3) 进行绘制会出现如下警告:power is not an integer, you should use nth-root instead, returning an empty interval, 当时没仔细看文档,还去傻傻的去问了作者,警告都提示我用 nthRoot, 我真是个睿智,hahaha…
在这里插入图片描述

functionPlot({
  target: '#root-finding',
  data: [{
    fn: 'nthRoot(x, 3)^2' // x^(2/3)
  }]
})

在这里插入图片描述


十二、动态割线:

在两条割线中设置 updateOnMouseMove 的示例,每条线将根据鼠标的当前位置动态计算

functionPlot({
  target: '#secant-update',
  yDomain: [-1, 9],
  data: [{
    fn: 'x^2',
    secants: [{
      x0: 2,
      updateOnMouseMove: true
    }, {
      x0: -2,
      updateOnMouseMove: true
    }]
  }]
})

在这里插入图片描述


十二、动态切线:

如果 updateOnMouseMove 设置为 true,则每当鼠标在画布内移动时都会计算切线

functionPlot({
  target: '#derivative-update',
  yAxis: {domain: [-1, 9]},
  data: [{
    fn: 'x^2',
    derivative: {
      fn: '2 * x',
      updateOnMouseMove: true
    }
  }]
})

在这里插入图片描述


十三、多条动态切线

具有多个函数的图像示例,每个函数都配置有一个导数对象,如上所述自动更新切线

functionPlot({
  target: '#derivative-update-multiple',
  data: [{
    fn: 'x * x',
    derivative: {
      fn: '2 * x',
      updateOnMouseMove: true
    }
  }, {
    fn: 'x * x * x',
    derivative: {
      fn: '3 * x * x',
      updateOnMouseMove: true
    }
  }]
})

在这里插入图片描述


十四、链接图

可以链接多个图像,当在原始图形上修改尖端的位置、图形比例或图形转换属性时,链接的图形会使用相同的事件发出信号,在以下示例中,a 触发内部事件,缩放操作在 a 和 b 上执行,但是当 b 触发事件时,缩放操作仅在 b 上执行

a = functionPlot({
  target: '#linked-a',
  height: 250,
  xAxis: {domain: [-10, 10]},
  data: [{ fn: 'x * x' }]
})
b = functionPlot({
  target: '#linked-b',
  height: 250,
  xAxis: {domain: [-10, 10]},
  data: [{ fn: '2 * x' }]
})
a.addLink(b)

在这里插入图片描述


十五:参数方程绘制:

用参数方程来渲染著名的蝴蝶曲线方程,方程是:
x = s i n ( t ) ( e c o s ( t ) − 2 c o s ( 4 t ) − s i n ( t 12 ) 5 ) y = c o s ( t ) ( e c o s ( t ) − 2 c o s ( 4 t ) − s i n ( t 12 ) 5 ) x = sin(t)(e^{cos(t)} - 2cos(4t) - sin(\tfrac{t}{12})^5) \\ y = cos(t)(e^{cos(t)} - 2cos(4t) - sin(\tfrac{t}{12})^5) x=sin(t)(ecos(t)2cos(4t)sin(12t)5)y=cos(t)(ecos(t)2cos(4t)sin(12t)5)

functionPlot({
  target: '#butterfly-curve',
  yAxis: {domain: [-4.428571429, 4.428571429]},
  xAxis: {domain: [-7, 7]},
  data: [{
    x: 'sin(t) * (exp(cos(t)) - 2 cos(4t) - sin(t/12)^5)',
    y: 'cos(t) * (exp(cos(t)) - 2 cos(4t) - sin(t/12)^5)',
    range: [-10 * Math.PI, 10 * Math.PI],
    fnType: 'parametric',
    graphType: 'polyline'
  }]
})

在这里插入图片描述


十五:极坐标方程绘制:

x 2 + y 2 = 1 x^2 + y^2 = 1 x2+y2=1的原方程可以用下面的极坐标方程表示
r = r 0 ; c o s ( θ − γ ) + a 2 − r 0 2 s i n 2 ( θ − γ ) r = r_0 ; cos(\theta - \gamma) + \sqrt{a^2 -r_0^2 sin^2(\theta - \gamma)} r=r0;cos(θγ)+a2r02sin2(θγ)
其中 θ \theta θ 是极角, a a a 是圆心 ( r 0 , γ ) (r_0, \gamma) (r0,γ) 的半径。
告诉 function-plot 呈现极坐标方程的选项在数据数组的每个项中定义,并且需要设置以下属性:
fnType: ‘polar’ 告诉函数 plot 渲染一个极坐标方程
r 的极坐标方程 θ
range = [-Math.PI, Math.PI] 极坐标方程中的 range 属性用于确定 θ 的可能值,记得在属性 samples 中设置了样本数
注意:function-plot 默认使用区间算术来创建一条线,而不是区间算术采样器集 graphType: ‘polyline’ 生成的矩形,它使用正常的单点评估。

functionPlot({
  target: '#polar-circle',
  yAxis: {domain: [-1.897959183, 1.897959183]},
  xAxis: {domain: [-3, 3]},
  data: [{
    r: 'r0 * cos(theta - gamma) + sqrt(a^2 - r0^2 * (sin(theta - gamma))^2)',
    scope: {
      a: 1,
      r0: 0,
      gamma: 0
    },
    fnType: 'polar',
    graphType: 'polyline'
  }]
})

在这里插入图片描述


  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0rta1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值