03.12.2014, 13:53
|
Профессор
|
|
Регистрация: 04.02.2012
Сообщений: 196
|
|
Несколько Canvas + Fluent interface
Вводные:
Была задача, грубо говоря, сделать рисовалку графов в канвасе.
Реализовал её в одном canvas. Теперь встала задача более сложная - на странице может быть много этих рисовалок , ну там 3-4-5, не важно, и нужно сделать fluent interface, да пока хотя бы сделать скрипт внешним (сейчас он html'ке).
Вообщем подскажите, как лучше это сделать с алгоритмической точки зрения, потому что на текущий момент я даже не знаю с какого конца взяться(
Имеем:
массивы объектов (дуг, вершин)
функции отрисовки
функции ивентов (клики и движение мыши)
Суть проблемы:
Для меня, самое сложное сейчас это наверное разграничить ивенты, чтобы на каждый canvas свой обработчик вешался. Конкретизирую:
сейчас у меня просто 3 ивента на элемент типа canvas, найденный по id внутри html. Но я не понимаю как заставить работать все, когда будет несколько canvas, а скрипт будет во внешнем файле.
Мои идеи:
Чутье мне подсказывает, что есть два варианта решения этой проблемы.
1 - это глобальный ивент на клики, внутри которого уже идет проверка - а на каком конкретно canvas произошел таки клик.
2 - это навешать на каждый canvas свой собственный ивент клика.
Реализацию первого варианта я еще смутно представляю, второй для меня дикость.
Финальный вопрос:
Какой из вариантов будет верным (правильным) или может есть еще способы, о которых я не догадываюсь?
|
|
03.12.2014, 14:20
|
Профессор
|
|
Регистрация: 12.12.2012
Сообщений: 1,398
|
|
Siend,
Если каждый инстанс рисовалки позиционируется как отдельный не зависящий ни от чего модуль, то тогда, конечно, правильней будет ему вешать свой обработчик на свой канвас.
Цитата:
|
2 - это навешать на каждый canvas свой собственный ивент клика.
Реализацию первого варианта я еще смутно представляю, второй для меня дикость.
|
При создании рисовалки кидаете ей в конструктор канвас с которым ей работать. Например создание рисовалок:
/**
* Массив рисовалок
* @type {Array}
*/
var grafEditors = [];
Array.prototype.forEach.call(document.querySelectorAll("canvas"), function (canvas) {
grafEditors.push(new GrafEditor(canvas));
});
Набросок рисовалки:
/**
* @class GrafEditor
* @constructor
* @param {HTMLCanvasElement} canvas
*/
var GrafEditor = function (canvas) {
this.canvas = canvas;
this.setHandlers();
};
/**
* @method setHandlers
*/
GrafEditor.prototype.setHandlers = function () {
this.canvas.addEventListener(...)
};
...
Последний раз редактировалось tsigel, 03.12.2014 в 14:42.
|
|
03.12.2014, 14:39
|
Профессор
|
|
Регистрация: 04.02.2012
Сообщений: 196
|
|
Ого, что-то я затупил. Можно объяснить эту строку:
Array.prototype.forEach.call(document.querySelectorAll("canvas"), function (canvas) {
grafEditors.push(new GrafEditor(canvas));
});
Насколько я понял, это что-то вроде:
для каждого элемента "canvas" выполняем функцию: добавляем в массив grafEditors (new GrafEditor(canvas) = что это не понял).
И сразу тогда уточню. В самом скрипте рисовалки соответственно создается структура графа, в моем случае это три массива объектов.
Так вот - как для каждого canvas заставить его видеть только свои три массива?
Поясню.
Сейчас у меня структура выглядит так:
<canvas id="canvas">
var canvas = document.getElementById('canvas');
var conn = []
var vers = []
var edges = []
Соответственно все элементы в единичном экземпляре, а я ведь по сути хочу чтобы для каждого canvas этот набор элементов был исключительно своим... И как это сделать я не понимаю(
|
|
03.12.2014, 14:46
|
Профессор
|
|
Регистрация: 12.12.2012
Сообщений: 1,398
|
|
Siend,
У вас не верный подход. Вы подошли к делу процедурно, а надо объектно ориентированно.
У вас за каждую рисовалку должен отвечать свой объект, у каждого этого объекта будут свои массивы точек объектов и т.д.
Выше я начал описывать создания объекта рисовалки.
Там "this.canvas" будет свой для каждого объекта. Почитайте статьи по ООП на этом сайте.
|
|
03.12.2014, 14:47
|
Профессор
|
|
Регистрация: 04.02.2012
Сообщений: 196
|
|
О, пришла в голову еще одна идея. Можно ли сделать так:
Ищем все элементы canvas (не по id, а именно сами canvas) и запихиваем их в массив canvas'oв, т.е. вместо
var canvas = document.getElementById('canvas');
будет что-то вроде
var canvas = [canvas1,canvas2,canvas3...]
А затем, уже анализировать - сколько их, создавать соответствующее кол-во массивов, и обработчиков? Ну т.е. обработчик все же делать 1, в котором смотреть просто какой конкретно элемент его вызвал?
|
|
03.12.2014, 14:49
|
Профессор
|
|
Регистрация: 04.02.2012
Сообщений: 196
|
|
Да то что подход не верный я понимаю, и суть ООП тоже улавливаю, но не применительно к javascript. До этого просто на шарпах писал, и там было все предельно прозрачно, а как в моем случае работать с каждой рисовалкой как с отдельным объектом я не врубаюсь(
|
|
03.12.2014, 14:49
|
Профессор
|
|
Регистрация: 12.12.2012
Сообщений: 1,398
|
|
Сообщение от Siend
|
Ого, что-то я затупил. Можно объяснить эту строку:
Array.prototype.forEach.call(document.querySelecto rAll("canvas"), function (canvas) {
grafEditors.push(new GrafEditor(canvas));
});
Насколько я понял, это что-то вроде:
для каждого элемента "canvas" выполняем функцию: добавляем в массив grafEditors (new GrafEditor(canvas) = что это не понял).
|
Да вы все верно поняли. Для каждого элемента канвас я создаю объект рисовалки (абстрактный). Ниже я начал описывать пример объекта рисовалки.
|
|
03.12.2014, 14:51
|
Профессор
|
|
Регистрация: 12.12.2012
Сообщений: 1,398
|
|
Siend,
Вообще плохо плодить переменные. У вас должен быть массив с рисовалками, каждая рисовалка - объект со всем что вам нужно + API для взаимодействия.
Если вы привыкли к строгой типизации - посмотрите в сторону TypeScript.
|
|
03.12.2014, 14:54
|
Профессор
|
|
Регистрация: 04.02.2012
Сообщений: 196
|
|
А, не заметил сразу, даже странно. А вот этот фрагмент:
GrafEditor.prototype.setHandlers = function () {
this.canvas.addEventListener(...)
это как-то связано с делигированием? Просто в делегатах я вообще не понимаю ничего, даже самого понятия делегат, хотя читал столько статей про них, и все равно не понимаю. Поэтому мои обработчики выглядят так:
canvas.onmousedown = myDown;
canvas.onmouseup = myUp;
canvas.onmousemove = myMove;
function myDown(e) {...}
function myUp(e) {...}
function myMove(e) {...}
|
|
03.12.2014, 14:59
|
Профессор
|
|
Регистрация: 04.02.2012
Сообщений: 196
|
|
Почитал про TypeSript, очень впечатлило, спасибо за эту наводку!!!
|
|
|
|