Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Несколько Canvas + Fluent interface (https://javascript.ru/forum/misc/52079-neskolko-canvas-fluent-interface.html)

Siend 03.12.2014 13:53

Несколько Canvas + Fluent interface
 
Вводные:
Была задача, грубо говоря, сделать рисовалку графов в канвасе.

Реализовал её в одном canvas. Теперь встала задача более сложная - на странице может быть много этих рисовалок , ну там 3-4-5, не важно, и нужно сделать fluent interface, да пока хотя бы сделать скрипт внешним (сейчас он html'ке).

Вообщем подскажите, как лучше это сделать с алгоритмической точки зрения, потому что на текущий момент я даже не знаю с какого конца взяться(

Имеем:
массивы объектов (дуг, вершин)
функции отрисовки
функции ивентов (клики и движение мыши)

Суть проблемы:
Для меня, самое сложное сейчас это наверное разграничить ивенты, чтобы на каждый canvas свой обработчик вешался. Конкретизирую:
сейчас у меня просто 3 ивента на элемент типа canvas, найденный по id внутри html. Но я не понимаю как заставить работать все, когда будет несколько canvas, а скрипт будет во внешнем файле.

Мои идеи:
Чутье мне подсказывает, что есть два варианта решения этой проблемы.
1 - это глобальный ивент на клики, внутри которого уже идет проверка - а на каком конкретно canvas произошел таки клик.
2 - это навешать на каждый canvas свой собственный ивент клика.
Реализацию первого варианта я еще смутно представляю, второй для меня дикость.

Финальный вопрос:
Какой из вариантов будет верным (правильным) или может есть еще способы, о которых я не догадываюсь?

tsigel 03.12.2014 14:20

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(...)
 
};

...

Siend 03.12.2014 14:39

Ого, что-то я затупил. Можно объяснить эту строку:
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 этот набор элементов был исключительно своим... И как это сделать я не понимаю(

tsigel 03.12.2014 14:46

Siend,
У вас не верный подход. Вы подошли к делу процедурно, а надо объектно ориентированно.

У вас за каждую рисовалку должен отвечать свой объект, у каждого этого объекта будут свои массивы точек объектов и т.д.

Выше я начал описывать создания объекта рисовалки.

Там "this.canvas" будет свой для каждого объекта. Почитайте статьи по ООП на этом сайте.

Siend 03.12.2014 14:47

О, пришла в голову еще одна идея. Можно ли сделать так:

Ищем все элементы canvas (не по id, а именно сами canvas) и запихиваем их в массив canvas'oв, т.е. вместо
var canvas = document.getElementById('canvas');

будет что-то вроде
var canvas = [canvas1,canvas2,canvas3...]

А затем, уже анализировать - сколько их, создавать соответствующее кол-во массивов, и обработчиков? Ну т.е. обработчик все же делать 1, в котором смотреть просто какой конкретно элемент его вызвал?

Siend 03.12.2014 14:49

Да то что подход не верный я понимаю, и суть ООП тоже улавливаю, но не применительно к javascript. До этого просто на шарпах писал, и там было все предельно прозрачно, а как в моем случае работать с каждой рисовалкой как с отдельным объектом я не врубаюсь(

tsigel 03.12.2014 14:49

Цитата:

Сообщение от Siend
Ого, что-то я затупил. Можно объяснить эту строку:
Array.prototype.forEach.call(document.querySelecto rAll("canvas"), function (canvas) {
  grafEditors.push(new GrafEditor(canvas));
});

Насколько я понял, это что-то вроде:
для каждого элемента "canvas" выполняем функцию: добавляем в массив grafEditors (new GrafEditor(canvas) = что это не понял).

Да вы все верно поняли. Для каждого элемента канвас я создаю объект рисовалки (абстрактный). Ниже я начал описывать пример объекта рисовалки.

tsigel 03.12.2014 14:51

Siend,
Вообще плохо плодить переменные. У вас должен быть массив с рисовалками, каждая рисовалка - объект со всем что вам нужно + API для взаимодействия.

Если вы привыкли к строгой типизации - посмотрите в сторону TypeScript.

Siend 03.12.2014 14:54

А, не заметил сразу, даже странно. А вот этот фрагмент:
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) {...}

Siend 03.12.2014 14:59

Почитал про TypeSript, очень впечатлило, спасибо за эту наводку!!!


Часовой пояс GMT +3, время: 22:27.