Несколько Canvas + Fluent interface
Вводные:
Была задача, грубо говоря, сделать рисовалку графов в канвасе. Реализовал её в одном canvas. Теперь встала задача более сложная - на странице может быть много этих рисовалок , ну там 3-4-5, не важно, и нужно сделать fluent interface, да пока хотя бы сделать скрипт внешним (сейчас он html'ке). Вообщем подскажите, как лучше это сделать с алгоритмической точки зрения, потому что на текущий момент я даже не знаю с какого конца взяться( Имеем: массивы объектов (дуг, вершин) функции отрисовки функции ивентов (клики и движение мыши) Суть проблемы: Для меня, самое сложное сейчас это наверное разграничить ивенты, чтобы на каждый canvas свой обработчик вешался. Конкретизирую: сейчас у меня просто 3 ивента на элемент типа canvas, найденный по id внутри html. Но я не понимаю как заставить работать все, когда будет несколько canvas, а скрипт будет во внешнем файле. Мои идеи: Чутье мне подсказывает, что есть два варианта решения этой проблемы. 1 - это глобальный ивент на клики, внутри которого уже идет проверка - а на каком конкретно canvas произошел таки клик. 2 - это навешать на каждый canvas свой собственный ивент клика. Реализацию первого варианта я еще смутно представляю, второй для меня дикость. Финальный вопрос: Какой из вариантов будет верным (правильным) или может есть еще способы, о которых я не догадываюсь? |
Siend,
Если каждый инстанс рисовалки позиционируется как отдельный не зависящий ни от чего модуль, то тогда, конечно, правильней будет ему вешать свой обработчик на свой канвас. Цитата:
/**
* Массив рисовалок
* @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(...)
};
...
|
Ого, что-то я затупил. Можно объяснить эту строку:
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 этот набор элементов был исключительно своим... И как это сделать я не понимаю( |
Siend,
У вас не верный подход. Вы подошли к делу процедурно, а надо объектно ориентированно. У вас за каждую рисовалку должен отвечать свой объект, у каждого этого объекта будут свои массивы точек объектов и т.д. Выше я начал описывать создания объекта рисовалки. Там "this.canvas" будет свой для каждого объекта. Почитайте статьи по ООП на этом сайте. |
О, пришла в голову еще одна идея. Можно ли сделать так:
Ищем все элементы canvas (не по id, а именно сами canvas) и запихиваем их в массив canvas'oв, т.е. вместо
var canvas = document.getElementById('canvas');
будет что-то вроде var canvas = [canvas1,canvas2,canvas3...] А затем, уже анализировать - сколько их, создавать соответствующее кол-во массивов, и обработчиков? Ну т.е. обработчик все же делать 1, в котором смотреть просто какой конкретно элемент его вызвал? |
Да то что подход не верный я понимаю, и суть ООП тоже улавливаю, но не применительно к javascript. До этого просто на шарпах писал, и там было все предельно прозрачно, а как в моем случае работать с каждой рисовалкой как с отдельным объектом я не врубаюсь(
|
Цитата:
|
Siend,
Вообще плохо плодить переменные. У вас должен быть массив с рисовалками, каждая рисовалка - объект со всем что вам нужно + API для взаимодействия. Если вы привыкли к строгой типизации - посмотрите в сторону TypeScript. |
А, не заметил сразу, даже странно. А вот этот фрагмент:
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) {...}
|
Почитал про TypeSript, очень впечатлило, спасибо за эту наводку!!!
|
Siend,
Вам надо почитать по основам ООП в js. Js основан на прототипах. То что мы кладем в прототип объекта - становится доступно ему как метод или параметр (объясняю на пальцах). В строке "GrafEditor.prototype.setHandlers = function () {" я кладу в прототип объекта "GrafEditor" метод "setHandlers" и потом я могу вызывать этот метод из контекста экземпляра данного объкта. Я хреново объясняю и лучше вам почитать. Многое прояснится и многое написать станет намного проще) |
Хорошо, просто время поджимает, научник ругается, и задачу нужно решить как можно скорее, так что боюсь пока-что придется гавнокодить (((
|
| Часовой пояс GMT +3, время: 16:30. |