• htm+JS实现绘制数学函数图像


    htm+JS实现绘制数学函数图像

    其中常用的函数可参见,JS中常用的Math方法 https://blog.51cto.com/u_10725738/5253407

    https://www.jb51.net/article/9151.htm

    JS(JavaScript)常用Math函数与用法说明

    方法描述示例
    abs(x)返回数的绝对值。Math.abs(-10)//返回10
    acos(x)返回数的反余弦值。Math.acos(1)//返回0
    asin(x)返回数的反正弦值。Math.asin(1)//返回1.5707963267948965
    atan(x)以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。Math.atan(0.50)//返回0.4636476090008061
    atan2(y,x)返回从 x 轴到点 (x,y) 的角度(介于 -PI/2 与 PI/2 弧度之间)。Math.atan2(5,5)//输出0.7853981633974483
    ceil(x)对数进行上舍入。

    Math.ceil(0.60)
    Math.ceil(-5.1) 

    //返回1
    //返回-5
    cos(x)返回数的余弦。Math.cos(0)//返回1
    exp(x)返回 e 的指数。Math.exp(5)//返回148.4131591025766
    floor(x)对数进行下舍入。Math.floor(0.60)
    Math.floor(-5.1)
    //返回0
    //返回-6
    log(x)返回数的自然对数(底为e)。Math.log(1)//返回0
    max(x,y)返回 x 和 y 中的最高值。Math.max(5,7)//返回7
    min(x,y)返回 x 和 y 中的最低值。Math.min(5,7)//返回5
    pow(x,y)返回 x 的 y 次幂。Math.pow(2,4)//返回16
    random()返回 0 ~ 1 之间的随机数。Math.random()//返回类似0.6654807284142312的随机数
    round(x)把数四舍五入为最接近的整数。Math.round(0.60)
    Math.round(-4.40)
    //返回1
    //返回-4
    sin(x)返回数的正弦。Math.sin(0)//返回0
    sqrt(x)返回数的平方根。Math.sqrt(0.64)//返回0.8
    tan(x)返回角的正切。Math.tan(10)//返回0.6483608274590866

    运行效果

     项目目录结构

     特别说明源码取自网络。

    数学函数绘图.html 源码:

    1. html>
    2. <html>
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>函数图像绘制工具title>
    6. <script type="text/javascript" src="js/funcImg.js">script>
    7. <style>
    8. #div-img {
    9. /* 此决定画布的宽高 */
    10. width: 500px;
    11. height: 500px;
    12. }
    13. #input-controller {
    14. padding: 10px;
    15. background-color: azure;
    16. }
    17. style>
    18. head>
    19. <body>
    20. <div id="input-controller">
    21. <div id="function">
    22. <button onclick="Add()">添加函数button>
    23. <span id="mod" style="display:none" name="0">
    24. <input type="color"/>y=
    25. <input type="text" value="x^3" name="Fun"/>
    26. <button onclick="Delete(this.parentNode)">Deletebutton>
    27. <input type="checkbox" onclick="reDraw()" checked="checked"/>Draw Line
    28. span>
    29. div>
    30. <div id="option">
    31. X:<input id="xLeftValue" /> ~
    32. <input id="xRightValue" />
    33. <br> Y:
    34. <input id="yLeftValue" /> ~
    35. <input id="yRightValue" />
    36. <br>
    37. <span id="show-size">Size:span>
    38. div>
    39. <button onclick="change()">画图button>
    40. div>
    41. <div id="main">
    42. <h1>函数图像绘制工具h1>
    43. <div id="div-img">
    44. <canvas id="graph">canvas>
    45. div>
    46. div>
    47. body>
    48. <script>
    49. const FONT_STYLE = "10px 黑体";
    50. const MIN = 1e-4;
    51. const MAX = 1e8;
    52. const EPS = 1e-12;
    53. const CANVAS = $("graph");
    54. const CONTEXT_2D = CANVAS.getContext("2d");
    55. const FUN_IMG_WIDTH = CANVAS.parentNode.clientWidth;
    56. const FUN_IMG_HEIGHT = CANVAS.parentNode.clientHeight;
    57. var xLeftValue = -FUN_IMG_WIDTH / 100; // x最左的值
    58. var xRightValue = FUN_IMG_WIDTH / 100;
    59. var yLeftValue = -FUN_IMG_HEIGHT / 100;
    60. var yRightValue = FUN_IMG_HEIGHT / 100;
    61. var tableX, tableY, countX, countY;
    62. var funStage = 0,
    63. mouseX, mouseY;
    64. var tmp;
    65. script>
    66. <script>
    67. CANVAS.width = FUN_IMG_WIDTH;
    68. CANVAS.height = FUN_IMG_HEIGHT;
    69. $("show-size").innerHTML = "Size:" + FUN_IMG_WIDTH + "*" + FUN_IMG_HEIGHT;
    70. CANVAS.onmousedown = function(ob) {
    71. mouseX = ob.layerX;
    72. mouseY = ob.layerY;
    73. funStage = 1;
    74. }
    75. CANVAS.onmousemove = function(ob) {
    76. if(funStage != 1) {
    77. return;
    78. }
    79. var NoX, NoY, det;
    80. NoX = ob.layerX;
    81. NoY = ob.layerY;
    82. det = (mouseX - NoX) / FUN_IMG_WIDTH * (xRightValue - xLeftValue);
    83. xLeftValue += det;
    84. xRightValue += det;
    85. det = (NoY - mouseY) / FUN_IMG_HEIGHT * (yRightValue - yLeftValue);
    86. yLeftValue += det;
    87. yRightValue += det;
    88. mouseX = NoX;
    89. mouseY = NoY;
    90. reDraw();
    91. update();
    92. }
    93. CANVAS.onmouseup = function(ob) {
    94. if(funStage == 1) {
    95. funStage = 0;
    96. reDraw();
    97. }
    98. }
    99. CANVAS.onmouseleave = function(ob) {
    100. if(funStage == 1) {
    101. funStage = 0;
    102. reDraw();
    103. }
    104. }
    105. CANVAS.onmousewheel = function(ob) {
    106. // 取消事件的默认动作
    107. ob.preventDefault();
    108. // 放大的比例
    109. var ScaleRate = 0.9;
    110. var detail;
    111. if(ob.wheelDelta) {
    112. detail = ob.wheelDelta;
    113. } else if(ob.detail) {
    114. detail = ob.detail;
    115. }
    116. if(detail > 0) {
    117. scale(ob.layerX, FUN_IMG_HEIGHT - 1 - ob.layerY, ScaleRate);
    118. } else {
    119. scale(ob.layerX, FUN_IMG_HEIGHT - 1 - ob.layerY, 1 / ScaleRate);
    120. }
    121. reDraw();
    122. update();
    123. }
    124. // 初始化
    125. reDraw();
    126. update();
    127. Add();
    128. script>
    129. html>

    funcImg.js 源码:

    1. function $(id) {
    2. return document.getElementById(id);
    3. }
    4. function getRandomColor() {
    5. var color = '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).substr(-6);
    6. return color;
    7. }
    8. function FunWork(f, x) {
    9. switch(f) {
    10. case "":
    11. {
    12. return x;
    13. break;
    14. }
    15. case "sin":
    16. {
    17. return Math.sin(x);
    18. break;
    19. }
    20. case "cos":
    21. {
    22. return Math.cos(x);
    23. break;
    24. }
    25. case "tan":
    26. {
    27. return Math.tan(x);
    28. break;
    29. }
    30. case "abs":
    31. {
    32. return Math.abs(x);
    33. break;
    34. }
    35. case "sqrt":
    36. {
    37. return Math.sqrt(x);
    38. break;
    39. }
    40. case "ln":
    41. {
    42. return Math.log(x);
    43. break;
    44. }
    45. case "log":
    46. {
    47. return Math.log(x) / Math.LN2;
    48. break;
    49. } //2为底
    50. case "lg":
    51. {
    52. return Math.log(x) / Math.LN10;
    53. break;
    54. } //10为底
    55. case "floor":
    56. {
    57. return Math.floor(x);
    58. break;
    59. }
    60. case "ceil":
    61. {
    62. return Math.ceil(x);
    63. break;
    64. }
    65. case "int":
    66. {
    67. return parseInt(x);
    68. break;
    69. }
    70. default:
    71. {
    72. return NaN;
    73. break;
    74. }
    75. }
    76. }
    77. function ChangeToPointY(y) {
    78. return FUN_IMG_HEIGHT - 1 - parseInt((y - yLeftValue) / (yRightValue - yLeftValue) * FUN_IMG_HEIGHT);
    79. }
    80. function isChar(c) {
    81. return(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
    82. }
    83. function isDigit(c) {
    84. return c >= '0' && c <= '9';
    85. }
    86. function priority(c) {
    87. switch(c) {
    88. case '(':
    89. return 0;
    90. break;
    91. case '+':
    92. return 1;
    93. break;
    94. case '-':
    95. return 1;
    96. break;
    97. case '*':
    98. return 2;
    99. break;
    100. case '/':
    101. return 2;
    102. break;
    103. case '^':
    104. return 3;
    105. break;
    106. default:
    107. return -1;
    108. break;
    109. }
    110. }
    111. // 是运算符
    112. function isOpt(c) {
    113. return priority(c) != -1;
    114. }
    115. function singleCalc(c, a, b) {
    116. if(c == '+') {
    117. return a + b;
    118. } else
    119. if(c == '-') {
    120. return a - b;
    121. } else
    122. if(c == '*') {
    123. return a * b;
    124. } else
    125. if(c == '/') {
    126. return a / b;
    127. } else
    128. if(c == '^') {
    129. return Math.pow(a, b);
    130. } else {
    131. return NaN;
    132. }
    133. }
    134. function getTable() {
    135. tmp = (xRightValue - xLeftValue + EPS) / 20;
    136. tableX = 1;
    137. countX = 0;
    138. countY = 0;
    139. while(tableX < tmp) {
    140. tableX *= 10;
    141. }
    142. while(tableX / 10 > tmp) {
    143. tableX /= 10;
    144. countX++;
    145. }
    146. if(tableX >= 1) {
    147. countX = 0;
    148. }
    149. if(tableX / 5 > tmp) {
    150. tableX /= 5;
    151. countX++;
    152. } else if(tableX / 2 > tmp) {
    153. tableX /= 2;
    154. countX++;
    155. }
    156. var i = parseInt(xLeftValue / tableX) + (xLeftValue > 0)
    157. for(; i * tableX < xRightValue; i++) {
    158. if(i == 0) {
    159. // y轴
    160. CONTEXT_2D.fillStyle = "black";
    161. } else {
    162. // 普通竖线
    163. CONTEXT_2D.fillStyle = "#CDB7B5";
    164. }
    165. tmp = (i * tableX - xLeftValue) / (xRightValue - xLeftValue) * FUN_IMG_WIDTH;
    166. var _width = 1;
    167. var _height = FUN_IMG_HEIGHT;
    168. CONTEXT_2D.fillRect(tmp, 0, _width, _height);
    169. // 竖线上的数字
    170. CONTEXT_2D.fillStyle = "red";
    171. CONTEXT_2D.font = FONT_STYLE;
    172. var _text = (i * tableX).toFixed(countX);
    173. var _x = tmp + 2;
    174. var _y = 10;
    175. CONTEXT_2D.fillText(_text, _x, _y);
    176. }
    177. tmp = (yRightValue - yLeftValue + EPS) / 20;
    178. tableY = 1;
    179. while(tableY < tmp) {
    180. tableY *= 10;
    181. }
    182. while(tableY / 10 > tmp) {
    183. tableY /= 10, countY++;
    184. }
    185. if(tableY / 5 > tmp) {
    186. tableY /= 5, countY++;
    187. } else if(tableY / 2 > tmp) {
    188. tableY /= 2, countY++;
    189. }
    190. if(tableY >= 1) {
    191. countY = 0;
    192. }
    193. var i = parseInt(yLeftValue / tableY) + (yLeftValue > 0);
    194. for(; i * tableY < yRightValue; i++) {
    195. // 横线
    196. if(i == 0) {
    197. // x轴
    198. CONTEXT_2D.fillStyle = "black";
    199. } else {
    200. // 普通横线
    201. CONTEXT_2D.fillStyle = "#CDB7B5";
    202. }
    203. tmp = (i * tableY - yLeftValue) / (yRightValue - yLeftValue) * FUN_IMG_HEIGHT;
    204. CONTEXT_2D.fillRect(0, FUN_IMG_HEIGHT - 1 - tmp, FUN_IMG_WIDTH, 1);
    205. // 横线上的数字
    206. CONTEXT_2D.fillStyle = "blue";
    207. CONTEXT_2D.font = FONT_STYLE;
    208. CONTEXT_2D.fillText((i * tableY).toFixed(countY), 0, FUN_IMG_HEIGHT - 1 - tmp);
    209. }
    210. }
    211. function drawArc(x, y) {
    212. CONTEXT_2D.beginPath();
    213. // arc(弧形),画圆
    214. CONTEXT_2D.arc(x, y, 1, 0, Math.PI * 2);
    215. CONTEXT_2D.closePath();
    216. CONTEXT_2D.fill();
    217. }
    218. function drawLine(lx, ly, px, py) {
    219. CONTEXT_2D.beginPath();
    220. CONTEXT_2D.moveTo(lx, ly);
    221. CONTEXT_2D.lineTo(px, py);
    222. CONTEXT_2D.closePath();
    223. CONTEXT_2D.stroke(); // 绘制
    224. }
    225. function reDraw() {
    226. CONTEXT_2D.clearRect(0, 0, FUN_IMG_WIDTH, FUN_IMG_HEIGHT);
    227. getTable();
    228. getFunction();
    229. }
    230. function change() {
    231. xLeftValue = parseFloat($("xLeftValue").value);
    232. xRightValue = parseFloat($("xRightValue").value);
    233. yLeftValue = parseFloat($("yLeftValue").value);
    234. yRightValue = parseFloat($("yRightValue").value);
    235. reDraw();
    236. }
    237. function update() {
    238. $("xLeftValue").value = xLeftValue;
    239. $("xRightValue").value = xRightValue;
    240. $("yLeftValue").value = yLeftValue;
    241. $("yRightValue").value = yRightValue;
    242. }
    243. function scale(x, y, times) {
    244. if(x < 0 || x >= FUN_IMG_WIDTH || y < 0 || y >= FUN_IMG_HEIGHT) return;
    245. if(times < 1 && (xRightValue - xLeftValue < MIN || yRightValue - yLeftValue < MIN)) {
    246. return;
    247. }
    248. if(times > 1 && (xRightValue - xLeftValue > MAX || yRightValue - yLeftValue > MAX)) {
    249. return;
    250. }
    251. x = xLeftValue + (xRightValue - xLeftValue) / FUN_IMG_WIDTH * x;
    252. y = yLeftValue + (yRightValue - yLeftValue) / FUN_IMG_HEIGHT * y;
    253. xLeftValue = x - (x - xLeftValue) * times;
    254. xRightValue = x + (xRightValue - x) * times;
    255. yLeftValue = y - (y - yLeftValue) * times;
    256. yRightValue = y + (yRightValue - y) * times;
    257. }
    258. function Calc(fun, X, Value) {
    259. var number = new Array(),
    260. opt = new Array(),
    261. F = new Array(),
    262. now = 0,
    263. f = "",
    264. tmp, a, b, sign = 1,
    265. base = 0,
    266. j;
    267. for(var i = 0; i < fun.length; i++) {
    268. for(j = 0; j < X.length; j++)
    269. if(X[j] == fun[i]) {
    270. if(i == 0 || isOpt(fun[i - 1])) now = Value[j];
    271. else now *= Value[j];
    272. break;
    273. }
    274. if(j == X.length)
    275. if(fun[i] == '(') F.push(f), f = "", opt.push('(');
    276. else
    277. if(fun[i] == ')') {
    278. number.push(now * sign);
    279. now = 0;
    280. sign = 1;
    281. base = 0;
    282. while((tmp = opt.pop()) != '(') {
    283. b = number.pop();
    284. a = number.pop();
    285. tmp = singleCalc(tmp, a, b);
    286. number.push(tmp);
    287. }
    288. now = FunWork(F.pop(), number.pop());
    289. } else
    290. if(fun[i] == '.') base = 1;
    291. else
    292. if(fun[i] == '+' && (i == 0 || priority(fun[i - 1]) != -1));
    293. else
    294. if(fun[i] == '-' && (i == 0 || priority(fun[i - 1]) != -1)) sign = -1;
    295. else
    296. if(fun[i] == 'e')
    297. if(i == 0 || isOpt(fun[i - 1])) now = Math.E;
    298. else now *= Math.E;
    299. else
    300. if(fun[i] == 'p' && fun[i + 1] == 'i') {
    301. if(i == 0 || isOpt(fun[i - 1])) now = Math.PI;
    302. else now *= Math.PI;
    303. i += 1;
    304. } else
    305. if(isDigit(fun[i]))
    306. if(base == 0) now = now * 10 + (fun[i] - '0');
    307. else base /= 10, now += base * (fun[i] - '0');
    308. else
    309. if(isChar(fun[i])) f += fun[i];
    310. else if(isOpt(fun[i])) {
    311. number.push(now * sign);
    312. now = 0;
    313. sign = 1;
    314. base = 0;
    315. var s = priority(fun[i]);
    316. if(s == -1) return 0;
    317. while(s <= priority(opt[opt.length - 1])) {
    318. b = number.pop();
    319. a = number.pop();
    320. tmp = singleCalc(opt.pop(), a, b);
    321. number.push(tmp);
    322. }
    323. opt.push(fun[i]);
    324. }
    325. }
    326. number.push(now * sign);
    327. while(opt.length > 0) {
    328. b = number.pop();
    329. a = number.pop();
    330. tmp = singleCalc(opt.pop(), a, b);
    331. number.push(tmp);
    332. }
    333. return number.pop();
    334. }
    335. function getFunction() {
    336. // group:函数(可能是复数)
    337. var group = document.getElementsByName("Fun");
    338. var x, y;
    339. var lax, lay;
    340. var px, py
    341. var color, outSide, type
    342. var ValueL, ValueR, ValueS, isDrawLine, tmp, TMP;
    343. for(var k = 1; k < group.length; k++) {
    344. var _funcItem = group[k].parentNode;
    345. outSide = 1;
    346. //type = _funcItem.children[0].value;
    347. // 颜色
    348. color = _funcItem.children[0].value;
    349. // 函数表达式
    350. funcExpression = group[k].value;
    351. // 是否画线(默认画点)
    352. isDrawLine = _funcItem.children[3].checked;
    353. CONTEXT_2D.fillStyle = CONTEXT_2D.strokeStyle = color;
    354. for(var i = 0; i < FUN_IMG_WIDTH; i++) {
    355. x = xLeftValue + (xRightValue - xLeftValue) / FUN_IMG_WIDTH * i;
    356. y = Calc(funcExpression, ['x'], [x]);
    357. if(isNaN(y)) {
    358. continue;
    359. }
    360. px = i;
    361. py = ChangeToPointY(y);
    362. if(y >= yLeftValue && y < yRightValue) {
    363. // 画圆
    364. drawArc(px, py);
    365. if(isDrawLine) {
    366. drawLine(lax, lay, px, py);
    367. }
    368. outSide = 0;
    369. } else {
    370. if(isDrawLine) {
    371. if(!outSide) {
    372. drawLine(lax, lay, px, py);
    373. }
    374. } else {}
    375. outSide = 1;
    376. }
    377. lax = px;
    378. lay = py;
    379. }
    380. }
    381. }
    382. function Add() {
    383. var newInput = $("mod").cloneNode(true);
    384. newInput.style.display = "block";
    385. newInput.children[0].value = getRandomColor();
    386. $("function").appendChild(newInput);
    387. }
    388. function Delete(node) {
    389. node.parentNode.removeChild(node);
    390. }

    附学习资料
    https://blog.csdn.net/Mingyueyixi/article/details/80964430

  • 相关阅读:
    安装好tomcat后,启动tomcat点击 startup.bat 窗口一闪而过怎么解决
    计算机毕业设计Java教评系统(源码+系统+mysql数据库+lw文档)
    go-gin-api 本地部署调试问题总结
    【 c++ 二元运算符重载,以<<(抽取符)为例,说清为什么它支持hex,endl等操作函数】
    C认证笔记 - 计算机通识 - IP基础
    vue 针试打印机实现
    Spark 框架概述
    NFTScan 浏览器再升级:优质数据服务新体验来袭
    【PTHREAD】线程退出与取消
    什么是网络API以及用例
  • 原文地址:https://blog.csdn.net/cnds123/article/details/127587986