23.08.2022, 23:17
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 456
|
|
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>
|
|
23.08.2022, 23:18
|
Аспирант
|
|
Регистрация: 21.08.2022
Сообщений: 57
|
|
Вот ссылка на график file:///C:/Users/%D0%98%D0%97%D0%9E/Desktop/JS1/Graf.html
|
|
23.08.2022, 23:28
|
Аспирант
|
|
Регистрация: 21.08.2022
Сообщений: 57
|
|
Rise,
Уважаемый Rise ! Спасибо. У Вас отлично получилось решение указанной проблемы с построением графиков. Но, почему то, не показаны чиловые оси X и Y. Это же, графики, не просто линии....
|
|
23.08.2022, 23:43
|
|
Кандидат Javascript-наук
|
|
Регистрация: 16.08.2018
Сообщений: 109
|
|
<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>
Последний раз редактировалось Alikberov, 24.08.2022 в 00:57.
|
|
24.08.2022, 07:59
|
Аспирант
|
|
Регистрация: 21.08.2022
Сообщений: 57
|
|
Замечено, что на балке, имеющей чередующиеся между собой неподвижные опоры и подвижные шарниры, при наличии участка, где если сделать подъём точки в бесшарнирном пролете, то можно получить вертикальное перемещение шарниров, как показано на картинке. Как с помощью JS описать этот процесс с выдачей необходимых результатов?
|
|
24.08.2022, 08:02
|
Аспирант
|
|
Регистрация: 21.08.2022
Сообщений: 57
|
|
Вот так лучше рассмотреть рисунки
|
|
24.08.2022, 11:09
|
Аспирант
|
|
Регистрация: 21.08.2022
Сообщений: 57
|
|
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));
|
|
24.08.2022, 21:21
|
|
Кандидат Javascript-наук
|
|
Регистрация: 16.08.2018
Сообщений: 109
|
|
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>
|
|
24.08.2022, 21:24
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,129
|
|
Сообщение от Alikberov
|
A вот такой вариант не подойдёт?
|
офигеть)))
|
|
24.08.2022, 22:29
|
Аспирант
|
|
Регистрация: 21.08.2022
Сообщений: 57
|
|
Rise, оказалось так всё просто.. Спасибо !
|
|
|
|