繁体   English   中英

在HTML5画布上下文上将钩子更改为lineWidth

[英]Hook changes to lineWidth on HTML5 canvas context

我想在实际像素中而不是作为lineWidth的比率来实施miterLimit。 为此,我想对lineWidth进行任何更改,并同时自动设置miterLimit。 我以前在对象上使用过自定义设置器,但是如果我替换了lineWidth设置器,我不知道有什么方法可以实际将设置值传递给实际的画布上下文。

是否有某种方式(与IE9 +兼容),我可以在不更改设置该值的行为的情况下侦听对象上给定键的更改?

您的getter / setter想法是一个好主意...

仅向您的上下文对象添加属性定义呢?

myLineWidth属性添加到上下文对象,然后使用context.myLineWidth而不是context.lineWidth设置线宽。

一些示例代码:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

Object.defineProperty(ctx, 'myLineWidth', {
    get: function() {
        return(this.lineWidth);
    },
    set: function(newWidth) {
        this.lineWidth=newWidth;
        console.log("Executed myLineWidth setter: ",this.lineWidth);        
    }
});

ctx.myLineWidth=5;
ctx.strokeRect(100,100,50,50);

使用封装的替代方法:

JavaScript确实具有真正的继承,因此无法继承和覆盖lineWidth

接下来最好的方法是封装上下文对象。 然后,所有编码人员都可以使用标准属性和方法语法使用上下文的封装版本(不需要myLineWidth)。 如果需要,这里有一个方法: http : //aboutcode.net/2011/10/04/efficiency-encapsulation-of-javascript-objects.html

为了记录上下文图纸,我做了类似的封装。 下面,我尝试从我的一个项目中截取封装代码。 您可以忽略我对drawImage和渐变的特殊处理,因为我需要从不需要获取的值中获取值,只需将这些方法添加到returnMethods []数组中即可。

您可以从以下示例代码开始:

// Log all context drawings
// Creates a proxy class wrapping canvas context
function LoggedContext(canvas,context) {
    var self = this;
    this.canvas=canvas;
    this.context=context;
    this.imageURLs=[];
    this.log=[];
    this.gradients=[];
    this.patterns=[];
    this.init(self);

}

// maintain urls of images used
LoggedContext.prototype.imageIndex=function(url){
    var i=a.indexOf(url);
    // found
    if(i>-1){ return(i); }
    // not found -- added
    a.push(url);
    return(a.length-1);
}
///////////////////////////////////////////
// These methods require special handling
// (drawImage:need image.src, gradients:need gradDefs & colors)
//
LoggedContext.prototype.drawImage=function(){
    this.context.drawImage.apply(this.context,arguments);
    var args = Array.prototype.slice.call(arguments);
    args[0]=arguments[0].src;
    args.unshift(2,"drawImage");
    var sArgs=JSON.stringify(args);
    this.log.push(sArgs);
    return(this);
}
//
LoggedContext.prototype.createLinearGradient =function(x1,y1,x2,y2){
    var gradient=this.context.createLinearGradient(x1,y1,x2,y2);
    gradient.context=this;
    gradient.gradientID=this.gradients.length;
    this.gradients.push({line:{x1:x1,y1:y1,x2:x2,y2:y2},stops:[]});
    gradient.baseAddColorStop=gradient.addColorStop;
    gradient.addColorStop=function(stop,color){
        this.context.gradients[this.gradientID].stops.push({stop:stop,color:color});
        this.baseAddColorStop(stop,color);
    }
    return(gradient);
}
//
LoggedContext.prototype.createPattern =function(i,r){
    var pattern=this.context.createPattern(i,r);
    pattern.patternID=this.patterns.length;
    this.patterns.push({src:i.src,repeat:r});
    return(pattern);
}
//
LoggedContext.prototype.createRadialGradient =function(sx,sy,sr,ex,ey,er){
    var gradient=this.context.createRadialGradient(sx,sy,sr,ex,ey,er);
    gradient.context=this;
    gradient.gradientID=this.gradients.length;
    this.gradients.push({circles:{sx:sx,sy:sy,sr:sr,ex:ex,ey:ey,er:er},stops:[]});
    gradient.baseAddColorStop=gradient.addColorStop;
    gradient.addColorStop=function(stop,color){
        this.context.gradients[this.gradientID].stops.push({stop:stop,color:color});
        this.baseAddColorStop(stop,color);
    }
    return(gradient);
}

// load the proxy object with all properties & methods of the context
LoggedContext.prototype.init=function(self){

    // define public context properties
    var properties={
        //
        fillStyle:"black",
        strokeStyle:"black",
        lineWidth:1,
        font:"10px sans-serif",
        //
        globalAlpha:1.00,
        globalCompositeOperation:"source-over",
        //
        shadowColor:"black",
        shadowBlur:0,
        shadowOffsetX:0,
        shadowOffsetY:0,
        //
        lineCap:"butt",   // butt,round,square
        lineJoin:"miter", // miter,round,miter
        miterLimit:10,
        //
        textAlign:"start",
        textBaseLine:"alphabetic",
    };

    // encapsulate public properties
    for (var i in properties) {
        (function(i) {
            if(!(i=="fillStyle")){
                Object.defineProperty(self, i, {
                    get: function () {
                        return properties[i];
                    },
                    set: function (val) {
                        this.log.push(JSON.stringify([1,i,val]));
                        properties[i] = val;
                        this.context[i]=val;
                    }
                })
            }else{
                Object.defineProperty(self, i, {
                    get: function () {
                        return properties[i];
                    },
                    set: function (val) {
                        if(typeof val ==="object"){
                            if(val.gradientID>=0){
                                this.log.push(JSON.stringify([1,i,"gradient",val.gradientID]));
                            }else if(val.patternID>=0){
                                this.log.push(JSON.stringify([1,i,"pattern",val.patternID]));
                            }
                        }else{
                            this.log.push(JSON.stringify([1,i,val]));
                        }
                        properties[i] = val;
                        this.context[i]=val;
                    }
                })
            }
        })(i);
    }

    // define public context methods
    var methods = ['arc','beginPath','bezierCurveTo','clearRect','clip',
      'closePath','fill','fillRect','fillText','lineTo','moveTo',
      'quadraticCurveTo','rect','restore','rotate','save','scale','setTransform',
      'stroke','strokeRect','strokeText','transform','translate','putImageData'];

    // encapsulate public methods
    for (var i=0;i<methods.length;i++){   
        var m = methods[i];
        this[m] = (function(m){
            return function () {
                this.context[m].apply(this.context, arguments);
                // "arguments" is not a real array--so convert it
                var args = Array.prototype.slice.call(arguments);
                args.unshift(2,m);
                var sArgs=JSON.stringify(args);
                this.log.push(sArgs);
                return(this);
        };}(m));
    }

    // define context methods that return values
    var returnMethods = ['measureText','getImageData','toDataURL',
      'isPointInPath','isPointInStroke'];

    // encapsulate return methods
    for (var i=0;i<returnMethods.length;i++){   
        var m = returnMethods[i];
        this[m] = (function(m){
            return function () {
                return(this.context[m].apply(this.context, arguments));
        };}(m));
    }

}  // end init()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM