Создание повторяющегося делегата JavaScript - PullRequest
2 голосов
/ 23 ноября 2010

Я создаю небольшую оболочку для холста HTML5, и я делаю одну вещь - возвращаю self / this из каждого из моих упакованных методов, чтобы упростить цепочку вызовов.

Из-за отсутствия лучшего имени я называю свою обертку Canvas.По сути, он объединяет холст и контекст.

Одна вещь, которую я сделал, это добавила следующие методы в Canvas.prototype

Canvas.fn = Canvas.prototype = {
    save: function () { this.ctx.save(); return this; },
    restore: function () { this.ctx.restore(); return this; },
    scale: function (x, y) { this.ctx.scale(x, y); return this; },
    rotate: function (angle) { this.ctx.rotate(angle); return this; },
    translate: function (x, y) { this.ctx.translate(x, y); return this; },
    transform: function (a,b,c,d,e,f) { this.ctx.transform(a,b,c,d,e,f); return this; },

Есть ли более простой способ добавить эти методы, используя некоторый делегат?Может быть, с массивом или именами функций?Обратите внимание, что некоторые методы принимают аргументы, и я хочу передать их как есть фактическому методу self.ctx.

Ответы [ 3 ]

2 голосов
/ 23 ноября 2010

Как то так?

var functionNames = ['save', 'restore', 'scale', 'rotate', 'translate', 'transform'];

for(var i = 0; i < functionNames.length; i++) {
    (function(funcName) {
        this[funcName] = function() {
            this.ctx[funcName].apply(this.ctx, arguments);
            return this;
        };
    )(functionNames[i]);
}
1 голос
/ 23 ноября 2010

Аналогично ответу Эрика , также основанному на http://seewhatever.de/blog/?p=440:

function CanvasWrapper(canvas)
{
    // Call this with new ... or not
    if(!(this instanceof CanvasWrapper)){
        return new CanvasWrapper(canvas);
    }

    var self = this,
        ctx = canvas.getContext('2d'),
        props = [
            'fillStyle', 'strokeStyle'
            // ...
        ],
        meths = [
            'fillRect', 'strokeRect', 'clearRect',
            'beginPath', 'closePath',
            'moveTo', 'lineTo', 'arc',
            'stroke'
            // ...
        ],
        nonChainableMeths = [
            'createLinearGradient'
        ],
        i, prop, meth;

    // Create and set jQuery-like property accessors
    // With no arguments they return the prop value
    // With one argument they set the prop value and return self
    function createAccessor(ctx, prop, self)
    {
        return function(){
            if(arguments.length == 1)
            {
                ctx[prop] = arguments[0];
                return self;
            }
            else
            {
                return ctx[prop];
            }
        }
    }
    for(i = 0; i < props.length; ++i)
    {
        prop = props[i];
        self[prop] = createAccessor(ctx, prop, self);
    }

    // Create and set chainable delegate methods
    function createDelegate(ctx, meth, self)
    {
        return function(){
            ctx[meth].apply(ctx, arguments);
            return self;
        }
    }
    for(i = 0; i < meths.length; ++i)
    {
        meth = meths[i];
        self[meth] = createDelegate(ctx, meth, self);
    }

    // Create and set non-chainable delegate methods
    function createNCDelegate(ctx, meth, self)
    {
        return function(){
            return ctx[meth].apply(ctx, arguments);
        }
    }
    for(i = 0; i < nonChainableMeths.length; ++i)
    {
        meth = nonChainableMeths[i];
        self[meth] = createNCDelegate(ctx, meth, self);
    }
    return self;
}
0 голосов
/ 23 ноября 2010

Продолжение ответа Эрика, который работает, дано ниже:

var funs = ['save', 'restore', 'scale', 'rotate', 'translate',
    'transform'];
var f;
for(var i = 0; i < funs.length; i++) {
    f = funs[i];
    self[f] = new Function("this.ctx." + 
            f + ".apply(this.ctx, arguments);  return this;");
}

Но мне не нравится использование конструктора Function, и моя функция сделана из строки.

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