Я думаю каждый, кто хотя бы раз сталкивался с 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 Добавлено описание профилирования