Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   ExtCanvas - мой маленький "фреймворк" (https://javascript.ru/forum/project/17722-extcanvas-mojj-malenkijj-frejjmvork.html)

DreamTheater 31.05.2011 01:48

ExtCanvas - небольшой фреймворк
 
Давно уж хотел написать нечто подобное, потому как штатных средств для анимации и отлова событий у элемента HTML5 Canvas не предусмотрено.

Сразу предупреждаю - проект очень сырой, написан за два вечера на коленке.

Итак представляю вашему вниманию фреймворк (как звучит-то :D ) ExtCanvas, от словосочетания Extended Canvas.

Что он умеет:
  • работать с фигурами как с объектами;
  • анимировать любые числовые параметры фигур, такие как координаты, размеры и т. п. (анимация CSS-цветов в разработке);
  • изменять параметры фигур без анимации;
  • обрабатывать события мыши для каждой фигуры в отдельности.
Что он не умеет:
  • обработчик событий не работает если фигура была нарисована не способом "beginPath - рисуем - closePath" (надеюсь в будущих выпусках спецификации это исправят).

Фреймворк работает полностью автономно, то есть не нужно никаких дополнительных библиотек, что в сумме с очень маленьким размером (14 кб в несжатом виде) делает его загрузку моментальной.

Инициализируется вот так:
var canvas = document.getElementById('canvasId');
var extcanvas = new ExtCanvas(canvas);

В качестве аргумента конструктору можно передавать элемент, контекст или просто ID элемента (хотя в идеале я хочу сделать выбор по CSS селектору как в jQuery), инициализация нативная.

Рисуются фигуры вот так:
var circle = extcanvas.addShape(function(x, y, radius) {

  // Эта функция выполняется в контексте CanvasRenderingContext2D, поэтому можно использовать this для рисования
  this.beginPath();
  this.arc(x, y, radius, 0, Math.PI * 2, false);
  this.closePath();

  this.fillStyle = '#F00';
  this.fill();

}, {

  // Эти параметры будут переданы как аргументы в предыдущую функцию
  // Если параметр не задекларирован здесь, то он не сможет принимать участие в анимации
  x: 100,
  y: 100,
  radius: 50

});

Для того чтобы изменить один или несколько параметров нужно написать:
circle.set({

  x: 150,
  y: 150

});

После этого окружность поменяет свои координаты. Те параметры, которые не были указаны, останутся без изменений.

Для того чтобы создать анимацию, например, плавного увеличения окружности в течение 500 мс, пишем вот так:
circle.animate({

  radius: 75

}, 500, function() {

  // Здесь можно написать функцию обратного вызова

});

Устанавливать обработчики событий можно двумя способами - аля jQuery и в стиле стандартного addEventListener:
circle.hover(function() {

  alert('Навели мышку.');

}, function() {

  alert('Отвели мышку.');

});

circle.addEventListener('mouseclick', function(event) {

  // Переменная event содержит в себе текущие координаты курсора, на каком объекте он расположен и т. п.
  alert('Клацнули мышкой');

});

Обработчики суммируются, то есть будут выполняться в порядке их установления (нужно будет, кстати, сделать возможность удаления обработчиков).

Сейчас фреймворк обрабатывает такие события:
  • mousemove
  • mouseover
  • mouseout
  • mousedown
  • mouseup
  • mouseclick
Посмотреть исходник с простенькой демонстрашкой можно тут. С красотами не заморачивался, нарисовал пару примитивов чтоб что-то мельтешило, фигурки можно таскать мышкой.

Программированием занимаюсь менее года, поэтому сильно не пинать. А вообще рад буду выслушать конструктивную критику и рекомендации.

DreamTheater 05.06.2011 17:40

И тишина... :(

dmitriymar 05.06.2011 18:52

Цитата:

Сообщение от DreamTheater
И тишина...

книга по канве . издательство орели-600 страниц. комментарии излишни. сделай с учётом всего-тогда обсудим. а сейчас нет смысла...

DreamTheater 05.06.2011 21:49

А как она точно называется?

dmitriymar 06.06.2011 10:44

Автор: Steve Fulton, Jeff Fulton
Название: HTML5 Canvas
Издательство: O'Reilly
Год: 2011

http://mirknig.com/knigi/web/1181403...l5-canvas.html

Micky_Holtern 15.06.2011 14:48

А почему решили писать свой фрэймворк, ведь есть jCanvaScript и libCanvas, например?

DreamTheater 15.06.2011 15:06

jCanvaScript не понравился, к сожалению уже не помню почему, а LibCanvas не ловит события мыши для отдельных фигурок.

Shock 24.06.2011 23:06

Цитата:

а LibCanvas не ловит события мыши для отдельных фигурок.
Что? О чём вы?

DNemo 24.06.2011 23:16

Хм... значит то я так читал. А Вы тот самый Shock? Оо

Shock 24.06.2011 23:21

Код, кстати, на удивление хорош. Конечно, есть некоторые ошибки, кое-где видны не очень хорошие знания JavaScript, но в общем - код на редкость качественный

Например:

this.setListener = function(type, listener) {

	switch (type) {
		case 'mouseover':
			this.mouseover.set(listener);
			break;

		case 'mouseout':
			this.mouseout.set(listener);
			break;

		case 'mousemove':
			this.mousemove.set(listener);
			break;

		case 'mousedown':
			this.mousedown.set(listener);
			break;

		case 'mouseup':
			this.mouseup.set(listener);
			break;

		case 'mouseclick':
			this.mouseclick.set(listener);
			break;
	}
}


Вполне можно заменить на:

this.setListener = function(type, listener) {

	if ( ['mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'mouseclick'].indexOf(type) === -1 ) return;

	this[type].set(listener);
}

Shock 24.06.2011 23:21

Да, тот самый =)

Shock 25.06.2011 00:07

Ваша функция toArray имеет ряд недостатков. Как по скорости, так и по логике. Лучше использовать что-то типа такого:
var toArray = function(o) {
	return Array.prototype.slice.call(o);
}

DNemo 25.06.2011 00:11

Цитата:

Сообщение от Shock (Сообщение 110376)
Код, кстати, на удивление хорош. Конечно, есть некоторые ошибки, кое-где видны не очень хорошие знания JavaScript, но в общем - код на редкость качественный

Например:

this.setListener = function(type, listener) {

	switch (type) {
		case 'mouseover':
			this.mouseover.set(listener);
			break;

		case 'mouseout':
			this.mouseout.set(listener);
			break;

		case 'mousemove':
			this.mousemove.set(listener);
			break;

		case 'mousedown':
			this.mousedown.set(listener);
			break;

		case 'mouseup':
			this.mouseup.set(listener);
			break;

		case 'mouseclick':
			this.mouseclick.set(listener);
			break;
	}
}


Вполне можно заменить на:

this.setListener = function(type, listener) {

	if ( ['mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'mouseclick'].indexOf(type) === -1 ) return;

	this[type].set(listener);
}

Да, профессионально программированием занимаюсь менее года.

Цитата:

Сообщение от Shock (Сообщение 110377)
Да, тот самый =)

Охренеть :blink:

Цитата:

Сообщение от Shock (Сообщение 110380)
Судя по коду вы хорошо знаете другой язык. Например, Java

Действительно, изучать программирование я начал именно с Java :)

Цитата:

Сообщение от Shock (Сообщение 110382)
Ваша функция toArray имеет ряд недостатков. Как по скорости, так и по логике. Лучше использовать что-то типа такого:
var toArray = function(o) {
	return Array.prototype.slice.call(o);
}

С этой функцией вышла целая история, надо было просто посмотреть как она реализована в какой-нибудь популярной библиотеке.

Shock 25.06.2011 00:14

Чего охренеть?
Я Вам вот что советую - не стоит распылять силы OS сообщества - лучше присоединяйтесь к LibCanvas ;)

DNemo 25.06.2011 00:17

Ну как что, Вы, можно сказать, великий Гуру для меня :thanks:
С удовольствием присоединюсь, все никак руки не дойдут разобраться с AtomJS.

Shock 25.06.2011 00:19

Пишите в Jabber shock@jabber.com.ua , пообщаемся)

Kolyaj 25.06.2011 21:26

Shock,
вы под IE не пишите, как я понимаю? :)

Цитата:

Сообщение от Shock
if ( ['mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'mouseclick'].indexOf(type) === -1 ) return;

indexOf у массивов нет в IE.

Цитата:

Сообщение от Shock
return Array.prototype.slice.call(o);

В IE с DOM-коллекциями такой финт не пройдёт.

Shock 25.06.2011 21:30

Зачем в Canvas-фреймворке костыли для IE, если даже с ними там ничего не заработает?

Kolyaj 25.06.2011 21:39

Цитата:

Сообщение от Shock
Зачем в Canvas-фреймворке костыли для IE

Действительно.

DreamTheater 25.06.2011 23:42

Ну почему же, в IE9 все замечательно работает, причем даже быстрее чем в других браузерах.

monolithed 26.06.2011 09:56

Цитата:

Сообщение от Shock
Зачем в Canvas-фреймворке костыли для IE, если даже с ними там ничего не заработает?

ну так, нас не только товарищ DNemo/DreamTheater читает, есть еще аудитория тех кто учатся писать под IE:
['mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'click'].join().search('mousemove') === -1;
//либо так:
'mouseover, mouseout, mousemove, mousedown, mouseup, click'.search('mousemove') === -1;

для тех, кто не знает как реализовать Array.indexOf():
(function($) {
    if(!$.indexOf) {
        $.indexOf = function(object) {
            var length = this.length -1, i = 0;
            while(++i <= length) {
                if(i in this && this[i] === object) {
                    return i;
                }
            }
            return -1;
        };
    }
})(Array.prototype);


Shock, у вас все проекты ориентированные на IE9+?

DNemo/DreamTheater, что за событие mouseclick?

Kolyaj 26.06.2011 10:20

Цитата:

Сообщение от monolithed
для тех, кто не знает как реализовать Array.indexOf():

Вы реализовали lastIndexOf.

monolithed 26.06.2011 10:34

Цитата:

Сообщение от Kolyaj
Вы реализовали lastIndexOf.

ага, забыл -1 дописать))

Riim 26.06.2011 12:17

Цитата:

Сообщение от monolithed
ага, забыл -1 дописать))

совсем плохо стало:
1. по прежнему lastIndexOf.
2. возможен бесконечный цикл (если массив пустой).
3. никогда не находит совпадение в последнем элементе ( alert([2, 1].indexOf(1));// -1 ).

Без поддержки второго аргумента (from) у меня получается так:
if (!('indexOf' in arrayProto)) {
	arrayProto.indexOf = function(item) {
		for (var i = 0, l = this.length; i < l; i++) {
			if (this[i] === item) return i;
		}
		return -1;
	};
}

Kolyaj 26.06.2011 12:37

Цитата:

Сообщение от monolithed
ага, забыл -1 дописать))

Нет, с вами сыграла злую шутку привычка оптимизировать то, что не тормозит. Массив нужно перебирать с начала.

monolithed 26.06.2011 12:51

Цитата:

Сообщение от Kolyaj
Нет, с вами сыграла злую шутку привычка оптимизировать то, что не тормозит. Массив нужно перебирать с начала.

Для меня просто работает поговорка: "Поспешишь, людей насмешишь", особенно когда только проснулся))

DreamTheater 26.06.2011 13:23

Цитата:

Сообщение от monolithed (Сообщение 110539)
DNemo/DreamTheater, что за событие mouseclick?

Событие mousedown вызывается когда кнопка мыши нажимается над объектом, mouseup - когда отпускается. А mouseclick срабатывает только если кнопка была нажата и отпущена над одним и тем же объектом.

monolithed 26.06.2011 13:29

Цитата:

Сообщение от DreamTheater
А mouseclick срабатывает только если кнопка была нажата и отпущена над одним и тем же объектом.

может все-таки click, а не mouseclick?

DreamTheater 26.06.2011 13:36

Цитата:

Сообщение от monolithed (Сообщение 110563)
может все-таки click, а не mouseclick?

Да, именно так :)

monolithed 26.06.2011 13:44

Цитата:

Сообщение от Riim
Без поддержки второго аргумента (from)

видимо как-то так, должно быть:
(function($) {
    if(!$.indexOf) {
        $.indexOf = function(object) {
            var length = this.length, i = arguments[1] || 0;
            i =  Math[i < 0 ? 'ceil' : 'floor'](i) - 1;
            //для отрицательных индексов
            if(i < 0) i += length;

            while(++i <= length) {
                if(i in this && this[i] === object) {
                    return i;
                }
            }
            return -1;
        };
    }
})(Array.prototype);

Shock 26.06.2011 14:00

Цитата:

ну так, нас не только товарищ DNemo/DreamTheater читает, есть еще аудитория тех кто учатся писать под IE
Я знаю. И считаю неправильным учить их тянуть костыли для IE туда, где они не нужны. Может, на сервере тоже не пользоваться indexOf? Когда не надо - мы отказываемся от кучи прекрасных вещей - accessors, querySelector, кучу методов в Array.prototype, const, не нужно реализовывать костыли для событий и так далее.

Shock 26.06.2011 14:01

PS. MooTools indexOf

monolithed 26.06.2011 14:04

Цитата:

Сообщение от Shock
И считаю неправильным учить их тянуть костыли для IE туда, где они не нужны.

Так как же они найдут работу? Мало кто из работодателей будет в восторге от сотрудника, который не знает особенностей браузеров
Цитата:

Сообщение от Shock
Может, на сервере тоже не пользоваться indexOf

Это другой разговор. хотя там своих нюансов полно
Цитата:

Сообщение от Shock
const

К сожалению, это и в IE9 не работает, а в Operа приравнивается к Variable Declaration ((

DreamTheater 26.06.2011 14:11

Вы сейчас рассуждаете как программисты, и я с вами полностью согласен - IE это жуткий геморрой на задницу разработчика, но тем не менее это один из популярнейших браузеров в мире. Большинство рядовых пользователей вообще не знает о том что такое браузер и, тем более, чем разные браузеры отличаются, они пользуются тем что предустановлено в их любимой Windows. Поэтому отказ от поддержки IE это потеря огромной части целевой аудитории, а значит и денег заказчика.

Shock 05.07.2011 18:25

DreamTheater, остановившись на Canvas вы УЖЕ отказались от Internet Explorer 8-

Цитата:

Так как же они найдут работу? Мало кто из работодателей будет в восторге от сотрудника, который не знает особенностей браузеров
Вот как раз сейчас большинство знает: "indexOf использовать нельзя", бездумно. А я хочу, чтобы они знали - indexOf использовать можно тогда, когда IE не является целевым браузером.


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