Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #21 (permalink)  
Старый 24.08.2022, 22:36
Аспирант
Отправить личное сообщение для IZUM Посмотреть профиль Найти все сообщения от IZUM
 
Регистрация: 21.08.2022
Сообщений: 57

Alikberov,
Графики, получились красивые, особенно, с осями координат. Спасибо за ответ. Однако, графики не имеют своих интервалов существования на оси Х, потому что они существуют на всей числовой оси Х и сходятся в одной точке (0, 0)
Ответить с цитированием
  #22 (permalink)  
Старый 24.08.2022, 22:54
Аспирант
Отправить личное сообщение для IZUM Посмотреть профиль Найти все сообщения от IZUM
 
Регистрация: 21.08.2022
Сообщений: 57

Alikberov, Только, что опробовал Ваш код, и оказалось, что Вы построили все возможные варианты построения графиков. Поэтому, очень прошу извинить меня за мою невнимательность и ещё раз большое спасибо. Ваш код не просто правильный, но совершенно полноценный.
Ответить с цитированием
  #23 (permalink)  
Старый 24.08.2022, 23:03
Аспирант
Отправить личное сообщение для IZUM Посмотреть профиль Найти все сообщения от IZUM
 
Регистрация: 21.08.2022
Сообщений: 57

Alikberov,
Было бы здорово, если бы Вы, общий код разделили на три кода: Соответственно, для одного графика, для графиков на разных интервалах, и графиков проходящих через (0,0). Сам, я боюсь чт что-нибудь не так сделаю или допушу досадную ошибку. Заранее благодарен.
Ответить с цитированием
  #24 (permalink)  
Старый 25.08.2022, 01:39
Аватар для Alikberov
Кандидат Javascript-наук
Отправить личное сообщение для Alikberov Посмотреть профиль Найти все сообщения от Alikberov
 
Регистрация: 16.08.2018
Сообщений: 109

Увы! Код написан довольно быстро и местами небрежно. Имеет ряд недоработок:
  • Отсутствует сетка, хотя параметр (строка 12) для указания размера ячеек имеется
  • Отсутствует клиппинг рабочей области и график может выйти за её пределы
  • Строка математического выражения к графику выводится чуть ли ни хаотически: Нужно добавить параметр для ручного позиционирования текста
  • Стиль текста никак не настраивается
  • Нужно добавить опцию подавления пунктирного разделителя
  • Самое неприятное: Построение графиков по оси Y (строки 127-134) имеет много грубых досадных ошибок (привет двойкам по математике) и я не успел отладить (методом проб и ошибок) эту часть кода
Цитата:
Было бы здорово, если бы Вы, общий код разделили на три кода
А там специально я код вызова функции разделил на три части (строки 152-170, 172-200 и 202-230), чтобы можно было скопировать и изменять по своему усмотрению.
Вот только комментарии не успел раскидать, из-за чего код слишком мутно выглядит.

Вот фрагмент с пояснениями.
var	meine_diagramme = {
	min_x: 0,		// Минимум по оси X на графике
	max_x: 10,		// Максимум по оси X на графике
	min_y: 0,		// Минимум по оси Y на графике
	max_y: 100,		// Максимум по оси Y на графике
	step_x: 1,		// Шаг цифровой разметки по оси X под графиком
	step_y: 20,		// Наш цифровой разметки по оси Y слева от графика
	width: 390,		// Ширина Canvas-области - масштаб графика 
	height: 120,	// Высота Canvas-области
	fn: [			// Здесь можем перечислить массивом все наши функции
		{
			x1: 0,			// Начальная точка на оси X
			x2: 100,		// Конечная точка на оси X
			color: "red",	// Цвет линии построения графика
			fn: "x**2"		// Ведущая функция на графике
		}
	]
};

// Создаём объект графика и передаём ему реквизиты
var grafik = new Functions(meine_diagramme);

// Добавляем его на страницу
document.body.appendChild(grafik.domElement);

// Теперь добавим вторую функцию
var mein_diagramm = {
		x1: 2.5,			// Начальная точка на оси X
		x2: 7.5,			// Конечная точка на оси X
		color: "blue",	// Цвет линии построения графика
		fn: "30*sin(10*x)+60"
	};

// Пауза перед добавлением второго графика
setTimeout(`grafik.draw([mein_diagramm])`, 5000);

// Пауза перед очищением области графика
setTimeout(`grafik.clear()`, 10000);

// Пауза перед отображением только второго графика`);
setTimeout(`grafik.draw([mein_diagramm])`, 15000);

// Пауза перед смещением оси путём коррекции минимума на сетке
setTimeout(`grafik.grid.min_x = -12; grafik.clear()`, 20000);

// Пауза перед отображением двух графиков
setTimeout(`mein_diagramm.x1 = -10; grafik.draw([mein_diagramm, meine_diagramme.fn[0]])`, 25000);

Последний раз редактировалось Alikberov, 25.08.2022 в 02:14.
Ответить с цитированием
  #25 (permalink)  
Старый 25.08.2022, 11:33
Аспирант
Отправить личное сообщение для IZUM Посмотреть профиль Найти все сообщения от IZUM
 
Регистрация: 21.08.2022
Сообщений: 57

Alikberov,
Уважаемый Alikberov, так как, я не такой опытный, как Вы, мне так и не удалось Ваш код разделить на три кода ( три типа построения графиков)
Убрал строки 152-170 с целью убрать первый тип графиков и, как и ожидалось ничего не получилось (где то ошибка). Вернее, после этого пошли ошибки за ошибкой, которые надо было исправлять. Убедительно прошу разделить общий файл на три по типам построения графиков. Если, есть возможность дайте хоть, какие нибудь главные комментарии.
Ответить с цитированием
  #26 (permalink)  
Старый 25.08.2022, 18:14
Аспирант
Отправить личное сообщение для IZUM Посмотреть профиль Найти все сообщения от IZUM
 
Регистрация: 21.08.2022
Сообщений: 57

Alikberov, Извините, опять поторопился со своим последним сообщением. Мне удалось Ваш код разделить на три кода ( три типа построения графиков). Правда, потратил на это несколько часов.
Ответить с цитированием
  #27 (permalink)  
Старый 26.08.2022, 04:29
Аватар для Alikberov
Кандидат Javascript-наук
Отправить личное сообщение для Alikberov Посмотреть профиль Найти все сообщения от Alikberov
 
Регистрация: 16.08.2018
Сообщений: 109

Вот Вам Конструктор Графиков с "горячей отладкой".
(Можно изменять любые параметры как мышкой, так и JSON.)

Правда, там не всё работает так, как хотелось бы мне. Но это поправимо в дальнейшем.

P.S.: Класс переименовал, добавил сетку и легенду.
Ответить с цитированием
  #28 (permalink)  
Старый 26.08.2022, 16:26
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 458

Alikberov,
График не реагирует на изменения шкалы, а должен по идее.

Могу подсказать, где подсмотреть можно на эту тему, если интересно.

Последний раз редактировалось Rise, 26.08.2022 в 16:34.
Ответить с цитированием
  #29 (permalink)  
Старый 26.08.2022, 16:30
Аспирант
Отправить личное сообщение для IZUM Посмотреть профиль Найти все сообщения от IZUM
 
Регистрация: 21.08.2022
Сообщений: 57

Alikberov, Я взял за основу Ваш код для построения графиков, но не смог нарисовать обыкновенные геометрические фигуры ромба и окружности, которые привязаны к определенной координате (См.картинку). Попробовал нарисовать обыкновенный отрезок, а он уехал, вобще, куда-то из области координат. Ваш код настолько насышен различными тегами, что я точно не смогу разобраться в чём дело. Видимо здесь более глубинные причины разрыва осей координат от геометрических фигур. Прошу, если возможно, упростить или сделать понятным высланный мной код HTML, который я выделил из общего Вашего кода. И, самое главное - нарисовать ромб и окружность, показанные на картинке. Их размеры должны быть сооизмеримы с координатными осями.
<!DOCTYPE html> 
<html><head>
<canvas id="canvas"></canvas>

<script>

var
canv = document.getElementById(`canvas`),
ctx = canv.getContext(`2d`); // рисуем в 2d

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: 40,
			min_y: -8,
			max_y: 8,
			step_x: 1,
			step_y: 20,
			width: 600,
			height: 200,
			fn: [
				{
					x1:0, x2:6,
					color: "red",
					fn: "x**2"
				}
			]
		}).domElement
	);
	
}


//линия 1

ctx.beginPath();
ctx.moveTo(200, 0);
ctx.lineTo(300, 1000);
ctx.stroke();
ctx.closePath();
</script>
<style>
canvas {
	display: block;
}
body {
	background-color: silver;
}
</style>
</head>

<body onload='Draw_Fn()'>
</body>
Изображения:
Тип файла: jpg РОМБ ОКРУЖНОСТЬ НАРИСОВАТЬ.jpg (7.9 Кб, 4 просмотров)

Последний раз редактировалось IZUM, 26.08.2022 в 16:34.
Ответить с цитированием
  #30 (permalink)  
Старый 26.08.2022, 17:25
Аватар для Alikberov
Кандидат Javascript-наук
Отправить личное сообщение для Alikberov Посмотреть профиль Найти все сообщения от Alikberov
 
Регистрация: 16.08.2018
Сообщений: 109

Сообщение от Rise Посмотреть сообщение
График не реагирует на изменения шкалы, а должен по идее.
Этo очень плохо!
У меня в двух браузерах (Chrome и Firefox ESR) отрабатывается нормально.
Сообщение от Rise Посмотреть сообщение
Могу подсказать, где подсмотреть можно на эту тему, если интересно.
Конечно!
Очень буду рад помощи в этой бесконечной и бессмыленной битве с кросс-браузерностью.

Сообщение от IZUM Посмотреть сообщение
Я взял за основу Ваш код для построения графиков, но не смог нарисовать обыкновенные геометрические фигуры ромба и окружности, которые привязаны к определенной координате (См.картинку).
И не мудрено, так как в основе этого класса ставилась задача простого вывода графика.
Класс просто не расчитывался для внешего вмешательства.
Сообщение от IZUM Посмотреть сообщение
Попробовал нарисовать обыкновенный отрезок, а он уехал, вобще, куда-то из области координат.
Чем подкидываете мне идею преобразования координат. Только это займёт время.
Сообщение от IZUM Посмотреть сообщение
Прошу, если возможно, упростить или сделать понятным высланный мной код HTML, который я выделил из общего Вашего кода. И, самое главное - нарисовать ромб и окружность, показанные на картинке. Их размеры должны быть сооизмеримы с координатными осями.
Я просто добавлю Вам метод для преобразования массива Ваших координат в координаты шкалы.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как вы относитесь к наркоманам? Maxmaxmaximus7 Оффтопик 7 05.02.2014 13:29
Как нарисовать Солнце средствами HTML 5 Canvas? Antohsa Элементы интерфейса 2 18.09.2013 01:19
Как в canvas нарисовать одно изображение на другом? Dimaz Общие вопросы Javascript 0 29.07.2013 20:11
Как нарисовать один canvas в другом BorodinKO Общие вопросы Javascript 0 06.04.2012 18:20