Я думаю каждый, кто хотя бы раз сталкивался с Canvas в встречал на своем пути одну не крайне не удобную вещь. При работе с Canvas для изменения любого параметра контекста или вызова метода, приходится обращаться сперва к контексту, а потом к методу/свойству — это очень напрягает.
Всегда хочется вот такой код:
Превратить в цепочку:
Sausage.js — 1268 байт (скоро будет меньше килобайта), решающие ваши проблемы.
«Luke, use __noSuchMethod__» — и все дела, скажете вы. А как же поддержка доисторических браузеров?
Все кто не равнодушен к Canvas, цепочками вызовов и к Lisp прошу под кат
Этот код (кроссбраузерный, делает тоже самое, что и первый блок) можно использовать, применив Sausage.js.
Такие цепочки похожи на сосиски — поэтому так и назвал Сосиска.js, участие лиспа тут, конечно никакого, просто любители оценят большое количество круглых скобок :)
При каждом смене контекста мне пришлось бы оббегать все методы и свойства контекста и для каждого создавать функцию — накладно и долго, поэтому пока отказался (сделаю позднее), но привел к подобному виду, используя цепочки функций.
Изначально я вообще не планировал добавлять __noSuchMethod__, но потом решил, что так будет правильно. И название библиотеки Sausage сейчас частично утратило свой смысл.
Браузеры, которые поддерживают __noSuchMethod__ могут работать с Sausage в любой удобной форме:
Для запуска профилирования, необходимо подключить версию со включенным профейлером и запустить профилирование.
В результате получим
— Для удобства необходимо собирать словарь методов/свойств (если использовать сосисичную нотацию)
— Прощай autocomplete (если использовать сосисичную нотацию)
— Вызовы немного медленее
— При точечной нотации невозможно вызвать меотды/свойства, которые есть у функций (length, call, apply, ...) нельзя —
— За счет словаря, отсутствия точки и применения цепочек — значительное сокращение объема кода после сжатия
— Возможность кроссбраузерно профилировать вызовы и считать количество вызовов
— Обработка «Пачкой»
Живой пример jsfiddle.net/azproduction/LUXwY
Не упакованная версия с комментами (9168 байт) sausage-js.googlecode.com/svn/trunk/Sausage.js
Упакованная версия (1268 байт) sausage-js.googlecode.com/svn/trunk/Sausage.min.js
Версия с профайлером sausage-js.googlecode.com/svn/trunk/Sausage-profile.js
Критика, пожелания и предложения приветствуются.
UPD Добавлено описание профилирования
Всегда хочется вот такой код:
var ctx = document.querySelectorAll('canvas')[0].getContext('2d'); ctx.fillStyle = '#eee'; ctx.strokeStyle = 'blue'; ctx.beginPath(); ctx.moveTo(10, 10) ctx.lineTo(100, 10) ctx.lineTo(100, 100) ctx.lineTo(10, 100) ctx.lineTo(10, 10) ctx.closePath() ctx.stroke() ctx.fill();
Превратить в цепочку:
ctx .fillStyle('#eee') .strokeStyle('blue') .beginPath() .moveTo(10, 10) .lineTo(100, 10) .lineTo(100, 100) .lineTo(10, 100) .lineTo(10, 10) .closePath() .stroke() .fill();
Sausage.js — 1268 байт (скоро будет меньше килобайта), решающие ваши проблемы.
«Luke, use __noSuchMethod__» — и все дела, скажете вы. А как же поддержка доисторических браузеров?
Все кто не равнодушен к Canvas, цепочками вызовов и к Lisp прошу под кат
Почему Sausage и при чем тут Lisp?
Этот код (кроссбраузерный, делает тоже самое, что и первый блок) можно использовать, применив Sausage.js.
// Собираем словарь для удобства (function(getContext, querySelectorAll, fillStyle, strokeStyle, beginPath, moveTo, lineTo, closePath, stroke, fill){ var canvasContext = $$(document)(querySelectorAll, 'canvas')(0)(getContext, '2d')(); $$(canvasContext, {fixedContext: true}) (fillStyle, '#eee') (strokeStyle, 'blue') (beginPath) (moveTo, 10, 10) (lineTo, 100, 10) (lineTo, 100, 100) (lineTo, 10, 100) (lineTo, 10, 10) (closePath) (stroke) (fill) (); }('getContext', 'querySelectorAll', 'fillStyle', 'strokeStyle', 'beginPath', 'moveTo', 'lineTo', 'closePath', 'stroke', 'fill'));
Такие цепочки похожи на сосиски — поэтому так и назвал Сосиска.js, участие лиспа тут, конечно никакого, просто любители оценят большое количество круглых скобок :)
Почему бы не эмулировать __noSuchMethod__?
При каждом смене контекста мне пришлось бы оббегать все методы и свойства контекста и для каждого создавать функцию — накладно и долго, поэтому пока отказался (сделаю позднее), но привел к подобному виду, используя цепочки функций.
Изначально я вообще не планировал добавлять __noSuchMethod__, но потом решил, что так будет правильно. И название библиотеки Sausage сейчас частично утратило свой смысл.
Браузеры, которые поддерживают __noSuchMethod__ могут работать с Sausage в любой удобной форме:
$$(canvasContext, {fixedContext: true}) (fillStyle, '#eee') (strokeStyle, 'blue') .beginPath() (moveTo, 10, 10) (lineTo, 100, 10) .lineTo(100, 100) (lineTo, 10, 100) (lineTo, 10, 10) (closePath) .stroke() .fill() ();
Примеры использования Sausage.js
Пример 1. Переключание контекста
context = {'foo': {'bar': '100500'}, 'bar': '888', 'zoo': /./}; // Создаем Сосиску с контекстом {'foo': {'bar': '100500'}, 'bar': '888', 'zoo': /./} result = $$(context) ('foo') // Переключаем контекст сосиски на {'bar': '100500'} ('bar', -1) // Меняем значение ('zoo') // Переключаем контекст на zoo (); // Получаем значение контекста - undefined т.к. у объекта foo нет свойства/метода zoo
Пример 2. Фиксированный контекст
context = {'foo': {'bar': '100500'}, 'bar': '888', 'zoo': /./}; // Создаем Сосиску с контекстом {'foo': {'bar': '100500'}, 'bar': '888', 'zoo': /./} result = $$(context, {fixedContext: true}) ('foo') // Переключаем контекст сосиски на {'bar': '100500'} ('bar', -1) // Меняем значение ('zoo') // Переключаем контекст на zoo (); // Получаем значение контекста - /./
Пример 3. Вызов функций — изменение значения контекста
context = {'foo': 1}; // Создаем Сосиску с контекстом {'foo': 1} result = $$(context) ('foo', 1000) // Меняем значение переменной контекста (function (context) { // Передаем функцию для обработки контекста return '' + context.foo / 2; // Возвращаем текущий контекст - строка '500' }) ('length') // Переключаем контекст на длину строки (function (context) { return typeof context; // Возвращаем текущий контекст - строка 'number' }) (); // Получаем значение контекста number
Пример 4. Обертка DOM
result = $$(document) ('getElementById', 'div1') ('style') ('width', '100px') // Меняем свойство ({ // Передаем объект для редактирования свойств/ вызовов методов пачкой height: '100px', color: 'red', border: 'solid 1px blue' }) (); // CSSStyleDeclaration Object
Пример 5. Обертка jQuery
result = $$(jQuery) (['#div2']) // Если первый аргумент массив и контекст - функция, то контекст вызывается с параметрами в массиве ('css', {width: '100px', height:'100px', color: 'red', border: 'solid 1px blue'}) ('animate', {width: '200px', height:'200px'}) (); // jQuery
Профилирование
Для запуска профилирования, необходимо подключить версию со включенным профейлером и запустить профилирование.
$$.profile(); // Ваш сосисочный код console && console.dir($$.profileEnd());
В результате получим
[anonymous function] Object { calls=2, time=0} [context call] Object { calls=1, time=0} [switching context] Object { calls=7, time=0} animate Object { calls=1, time=5} bar Object { calls=2, time=0} width Object { calls=1, time=0}
Минусы
— Для удобства необходимо собирать словарь методов/свойств (если использовать сосисичную нотацию)
— Прощай autocomplete (если использовать сосисичную нотацию)
— Вызовы немного медленее
— При точечной нотации невозможно вызвать меотды/свойства, которые есть у функций (length, call, apply, ...) нельзя —
$$([1,2,3]).length()();, можно — $$([1,2,3])('length')();Плюсы
— За счет словаря, отсутствия точки и применения цепочек — значительное сокращение объема кода после сжатия
— Возможность кроссбраузерно профилировать вызовы и считать количество вызовов
— Обработка «Пачкой»
Ссылки
Живой пример jsfiddle.net/azproduction/LUXwY
Не упакованная версия с комментами (9168 байт) sausage-js.googlecode.com/svn/trunk/Sausage.js
Упакованная версия (1268 байт) sausage-js.googlecode.com/svn/trunk/Sausage.min.js
Версия с профайлером sausage-js.googlecode.com/svn/trunk/Sausage-profile.js
Критика, пожелания и предложения приветствуются.
UPD Добавлено описание профилирования
