IZUM,
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Графики</title> </head> <body> <canvas id="canvas" width="400" height="200" style="border:1px solid grey"></canvas> <script> function createPath(x1, x2, y, sx, sy) { const path = new Path2D(); for (let x = x1; x <= x2; x++) { if (x == x1) { path.moveTo(x * sx, y(x) * sy); } else { path.lineTo(x * sx, y(x) * sy); } } return path; } const ctx = canvas.getContext('2d'); ctx.translate(0, 200); ctx.scale(1, -1); ctx.strokeStyle = 'red'; ctx.stroke(createPath(0, 2, x => x + 1, 30, 1)); ctx.strokeStyle = 'green'; ctx.stroke(createPath(2, 5, x => x ** 2 + 4, 30, 1)); ctx.strokeStyle = 'blue'; ctx.stroke(createPath(5, 10, x => x ** 2 + 2 * x + 1, 30, 1)); </script> </body> </html> |
Вот ссылка на график file:///C:/Users/%D0%98%D0%97%D0%9E/Desktop/JS1/Graf.html
|
Rise,
Уважаемый Rise ! Спасибо. У Вас отлично получилось решение указанной проблемы с построением графиков. Но, почему то, не показаны чиловые оси X и Y. Это же, графики, не просто линии.... |
<html><head> <script> function DrawFn() { var ctx = document.querySelector("canvas").getContext("2d"); var width = ctx.canvas.width; var height = ctx.canvas.height; var size_x = width - 40; var size_y = height - 24; var drawer; var i, x0, x1, x2, x, y, max_y, el, fn, range; var els = document.getElementsByName("Fn_X"); ctx.save(); ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); ctx.strokeStyle = "black"; ctx.fillStyle = "black"; ctx.beginPath(); ctx.translate(32, 8); ctx.rect(0, 0, size_x, size_y); // Черртим рамку for(i = 0; i <= 10; ++ i) { // Размечаем ось X ctx.moveTo(i * size_x / 10, 0); ctx.lineTo(i * size_x / 10, size_y); ctx.fillText(String(i), i * size_x / 10 - 4, size_y + 16); if(i & 1) continue; // Размечаем ось Y ctx.moveTo(0, i * size_y / 10); ctx.lineTo(size_x, i * size_y / 10); ctx.fillText(String(i * 10), -16, (10 - i) * size_y / 10 + 8); } ctx.stroke(); // Очищаем основную област графика ctx.clearRect(8, 8, size_x - 16, size_y - 16); for(i = 0; i < els.length; ++ i) { ctx.strokeStyle = els[i].style.color; // Цвет линии графика соответствует цвету input-текста fn = els[i].value.split(/:/)[1]; // Выражение функции справа от двоеточия range = els[i].value.split(/:/)[0].split(".."); // Интервал участка задаётся форматом "от..до" слева от двоеточия x1 = parseInt(range[0]); x2 = parseInt(range[1]); max_y = size_y; ctx.beginPath(); drawer = ctx.moveTo.bind(ctx); for(x0 = size_x * x1 / 10; x0 < size_x * x2 / 10; ++ x0) { x = x0 / size_x * 10; try { with(Math) { drawer(x0, y = size_y - eval(fn) * size_y / 100); max_y = Math.min(max_y, y); } } catch(err) { break; } drawer = ctx.lineTo.bind(ctx); } ctx.stroke(); ctx.beginPath(); ctx.moveTo(x0, 0); ctx.lineTo(x0, size_y); ctx.setLineDash([1, 2]); ctx.strokeStyle = "black"; ctx.stroke(); ctx.setLineDash([]); fn = fn.replace(/\*\*2/g, "\u00B2").replace(/\*\*3/g, "\u00B3").replace(/\*/g, ""); ctx.fillText(fn, size_x * (x1 + (x2 - x1) / 2) / 10, max_y); } ctx.restore(); } </script> </head> <body onload='DrawFn()'> Y2(x)=<input type=text name=Fn_X value='0..2:x+1' onchange='DrawFn()' style=color:magenta><br> Y3(x)=<input type=text name=Fn_X value='2..5:x**2+4' onchange='DrawFn()' style=color:red><br> Y4(x)=<input type=text name=Fn_X value='5..10:x**2-2*x+1' onchange='DrawFn()' style=color:orange><br> <canvas width=400px height=200px></canvas> </body> |
Вложений: 2
Замечено, что на балке, имеющей чередующиеся между собой неподвижные опоры и подвижные шарниры, при наличии участка, где если сделать подъём точки в бесшарнирном пролете, то можно получить вертикальное перемещение шарниров, как показано на картинке. Как с помощью JS описать этот процесс с выдачей необходимых результатов?
|
Вложений: 1
Вот так лучше рассмотреть рисунки
|
Вложений: 1
Rise,
Я попробовал к построенным Вами графикам пристроить оси координат, но получилось так, что все графики оказались сдвинутыми влево, в отрицательную область Х. Помогите, пожалуйста исправить этот сдвиг. [HTML]<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link href="./GrafPL.css" rel="stylesheet"> </head> <body style= "margin": 0;> <canvas id="canvas_plot" width="700" height="500"></canvas> <script src="./GrafPL.js"></script> </body> </html>[/HTML]const canvasPlot = document.getElementById(`canvas_plot`); const ctx = canvasPlot.getContext(`2d`); //Рисуем сетку const canvasPlotWidth = canvasPlot.clientWidth; const canvasPlotHeight = canvasPlot.clientHeight; const scaleX = 30; //расстояние между элементами сетки по Х const scaleY = 30; //расстояние между элементами сетки по Y //Рисуем главные оси // Обычное расположение осей //const xAxis = canvasPlotWidth / 2; //const yAxis = canvasPlotHeight / 2; // Уточнённое расположение осей за счёт сдвига осей const xAxis = Math.round(canvasPlotWidth / scaleX / 2) * scaleX; const yAxis = Math.round(canvasPlotHeight / scaleY / 2) * scaleY; // Выбор шрифта и его вид, размер ctx.font = `${Math.round(scaleX / 2)}px Arial`; ctx.textAlign = `left`; ctx.textBaseline = `top`; ctx.beginPath(); ctx.strokeStyle = `#f5f0e8`; var zz = 5; //Зазор между осями и числами нумерации чисел for (let i = 0; i <= canvasPlotWidth; i = i + scaleX) { ctx.moveTo(i, 0); ctx.lineTo(i, canvasPlotHeight); // нанесение вертикальных линий разметки ctx.fillText((i - xAxis) / scaleX, i + zz, yAxis + zz); //нанесение числовых значений на ось Х } for (let i = 0; i <= canvasPlotHeight; i = i + scaleY) { ctx.moveTo(0, i); ctx.lineTo(canvasPlotWidth, i); // нанесение горизонтальных линий разметки ctx.fillText((yAxis - i) / scaleY, xAxis + zz, i + zz); //нанесение числовых значений на ось Y } ctx.stroke(); ctx.closePath(); //закрыть путь, чтобы рисовать новые линии другим цветом var zxy = 20; //Зазор между осями и обозначением этих осей x,y ctx.beginPath(); ctx.strokeStyle = `#000000`; ctx.moveTo(xAxis, 0); ctx.lineTo(xAxis, canvasPlotHeight); ctx.fillText(`y`, xAxis - zxy, 0 ); // означение оси Y ctx.moveTo(0, yAxis); ctx.lineTo(canvasPlotWidth, yAxis); ctx.fillText(`x`, canvasPlotWidth - zxy, yAxis - zxy ); // означение оси X ctx.stroke(); ctx.closePath(); //закрыть путь, чтобы рисовать новые линии другим цветом //ПРЕОБРАЗОВАНИЕ CANVAS СИСТЕМУ КООРДИНАТ В ДЕКАРТОВУ СИСТЕМУ КООРДИНАТ // Рисуем график функции //ctx.fillStyle = `#ff0000`; // цвет графика чёрный //ctx.lineWidth = 0.5 //толщина линии //for (let i = 0; i <= canvasPlotWidth; i++) { //const x = (i - xAxis) / scaleX; //const y = Math.pow(x, 2); //степенная фукция, y=x^2 //ctx.fillRect(x * scaleX + xAxis, yAxis - scaleY * y, 4, 4); //} function createPath(x1, x2, y, sx, sy) { const path = new Path2D(); for (let x = x1; x <= x2; x++) { if (x == x1) { path.moveTo(x * sx, y(x) * sy); } else { path.lineTo(x * sx, y(x) * sy); } } return path; } ctx.translate(0, 200); ctx.scale(1, -0.5); ctx.strokeStyle = 'red'; ctx.lineWidth = 4 //толщина линии ctx.stroke(createPath(0, 2, x => x + 1, 30, 1)); ctx.strokeStyle = 'green'; ctx.stroke(createPath(2, 5, x => x ** 2 + 4, 30, 1)); ctx.strokeStyle = 'blue'; ctx.stroke(createPath(5, 10, x => x ** 2 + 2 * x + 1, 30, 1)); |
A вот такой вариант не подойдёт?
<html><head> <script> class Functions { constructor(props) { this.grid = { min_x :props && "min_x" in props ? props.min_x : -50, max_x :props && "max_x" in props ? props.max_x : 100, min_y :props && "min_y" in props ? props.min_y : -80, max_y :props && "max_y" in props ? props.max_y : 100, step_x :(props && props.step_x) || 10, step_y :(props && props.step_y) || 20, size :(props && props.size) || 25 }; this.domElement = document.createElement("canvas"); this.domElement.width = props && props.width || 640; this.domElement.height = props && props.height || 480; this.context = this.domElement.getContext("2d"); this.clear(); if(props && props.fn) this.draw(props.fn); return this; } clear() { var from_x = 20, last_x = this.domElement.width - 8; var from_y = 8, last_y = this.domElement.height - 24; var width = last_x - from_x; var height = last_y - from_y; var size_x = this.grid.max_x - this.grid.min_x; var size_y = this.grid.max_y - this.grid.min_y; var left, right, top, bottom; var i, x, y; this.context.fillStyle = "white"; this.context.fillRect(0, 0, this.domElement.width, this.domElement.height); this.context.strokeStyle = "black"; this.context.fillStyle = "black"; this.context.textAlign = "right"; this.context.beginPath(); if(this.grid.min_x * this.grid.max_x >= 0 && this.grid.min_y * this.grid.max_y >= 0) { this.context.rect(from_x, from_y, width, height); left = from_x + 2; right = last_x - 2; top = from_y + 2; bottom = last_y - 2; } else { left = from_x - width / size_x * this.grid.min_x; right = left; top = last_y + height / size_y * this.grid.min_y; bottom = top; this.context.moveTo(left, from_y); this.context.lineTo(left, last_y); this.context.moveTo(from_x, top); this.context.lineTo(last_x, top); } for(i = this.grid.min_x; i <= this.grid.max_x; i += this.grid.step_x) { x = from_x + (i - this.grid.min_x) / size_x * width; this.context.moveTo(x, top - 2); this.context.lineTo(x, top + 2); this.context.moveTo(x, bottom - 2); this.context.lineTo(x, bottom + 2); this.context.fillText(String(i), x + 4, bottom + 14); } for(i = this.grid.min_y; i <= this.grid.max_y; i += this.grid.step_y) { y = from_y + (i - this.grid.min_y) / size_y * height; this.context.moveTo(left - 2, y); this.context.lineTo(left + 2, y); this.context.moveTo(right - 2, y); this.context.lineTo(right + 2, y); this.context.fillText(String((this.grid.max_y - i + this.grid.min_y)), left - 4, y + 8); } this.context.stroke(); this.context.fillText("X", right, bottom); this.context.textAlign = "left"; this.context.fillText("Y", left, top + 12); return this; } draw(functions) { var from_x = 20, last_x = this.domElement.width - 8; var from_y = 8, last_y = this.domElement.height - 24; var width = last_x - from_x; var height = last_y - from_y; var size_x = this.grid.max_x - this.grid.min_x; var size_y = this.grid.max_y - this.grid.min_y; for(var grafic of functions) { var min_x = Math.max(this.grid.min_x, grafic.x1 || 0); var max_x = Math.min(this.grid.max_x, grafic.x2 || 0); var min_y = Math.max(this.grid.min_y, grafic.y1 || 0); var max_y = Math.min(this.grid.max_y, grafic.y2 || 0); var fn = grafic.fn; var left = from_x - this.grid.min_x / size_x * width + width / size_x * min_x; var right = last_x - this.grid.max_x / size_x * width + width / size_x * max_x; var top = last_y + this.grid.min_y / size_y * height + height / size_y * min_y; var bottom = last_y + this.grid.min_y / size_y * height + height / size_y * max_y; var maxi, exprs; this.context.textAlign = "right"; if(fn) { exprs = fn.replace(/\*\*2/g, "\u00B2").replace(/\*\*3/g, "\u00B3").replace(/\*/g, ""); fn = fn.replace(/(cos|sin|tan|exp)/g, "Math.$1"); if(isFinite(grafic.x1) && isFinite(grafic.x2)) { this.context.beginPath(); this.context.strokeStyle = grafic.color || "black"; maxi = this.grid.min_y; for(var x0 = left; x0 < right; ++ x0) { var x = (x0 - from_x) / width * size_x + this.grid.min_x, y = 0; try { y = eval(fn); y = y / size_y * height; maxi = Math.max(maxi, y); } catch(err) { } this.context.lineTo(x0, bottom - y); } this.context.stroke(); this.context.beginPath(); this.context.moveTo(x0, from_y); this.context.lineTo(x0, last_y); this.context.setLineDash([1, 2]); this.context.strokeStyle = "black"; this.context.stroke(); this.context.setLineDash([]); this.context.fillText(exprs, left + (right - left) / 2, bottom - maxi / 2); } else if(isFinite(grafic.y1) && isFinite(grafic.y2)) { this.context.beginPath(); this.context.strokeStyle = grafic.color || "black"; maxi = this.grid.min_x; for(var y0 = top; y0 < bottom; ++ y0) { var x = 0, y = (bottom - y0 - from_y) / height * size_y + this.grid.min_y; try { x = eval(fn); x = x / size_x * width; maxi = Math.max(maxi, x); } catch(err) { } this.context.lineTo(left - x, last_y - y0 - (this.grid.min_y) / size_y * height); } this.context.stroke(); this.context.beginPath(); this.context.moveTo(from_x, last_y - y0 - (this.grid.min_y) / size_y * height); this.context.lineTo(last_x, last_y - y0 - (this.grid.min_y) / size_y * height); this.context.setLineDash([1, 2]); this.context.strokeStyle = "black"; this.context.stroke(); this.context.setLineDash([]); this.context.fillText(exprs, left + maxi / 2, top + (bottom - top) / 2); } } } } } function Draw_Fn() { document.body.appendChild( new Functions({ min_x: 0, max_x: 10, min_y: 0, max_y: 100, step_x: 1, step_y: 20, width: 390, height: 120, fn: [ { x1:0, x2:100, color: "red", fn: "x**2" } ] }).domElement ); document.body.appendChild(document.createElement("hr")); document.body.appendChild( new Functions({ min_x: 0, max_x: 10, min_y: 0, max_y: 100, step_x: 1, step_y: 20, width: 390, height: 120, fn: [ { x1:-1, x2:2, color: "magenta", fn: "x+1" }, { x1:2, x2:5, color: "red", fn: "x**2+4" }, { x1:5, x2:10, color: "orange", fn: "x**2-2*x+1" } ] }).domElement ); document.body.appendChild(document.createElement("hr")); document.body.appendChild( new Functions({ min_x: -5, max_x: 10, min_y: -50, max_y: 100, step_x: 5, step_y: 25, width: 390, height: 240, fn: [ { x1:0, x2:10, color: "red", fn: "x**2" }, { y1:-35, y2:50, color: "blue", fn: "sin(y/10)" }, { x1:-5, x2:10, color: "green", fn: "exp(x/2)" } ] }).domElement ); } </script> <style> canvas { display: block; } body { background-color: silver; } </style> </head> <body onload='Draw_Fn()'> </body> |
Цитата:
|
Rise, оказалось так всё просто.. Спасибо !
|
Часовой пояс GMT +3, время: 20:48. |