[英]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.