Несколько 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, очень впечатлило, спасибо за эту наводку!!!
|
Часовой пояс GMT +3, время: 05:28. |