注:私は SO質問 を参照しましたが、私の場合は役に立ちません。
1)以前の境界線を維持しようとしていますが、現時点では、スケーリング中に境界線を再計算します。
オブジェクトのスケーリング中に境界線の増加を自動的に停止するコードを以下に追加しました。ここで問題となるのは、オブジェクトに5pxの境界線を追加したのですが、オブジェクトを拡大縮小すると、前に追加した境界線が維持されません。
canvas.on('object:scaling', (e) => {
var o = e.target;
if (!o.strokeWidthUnscaled && o.strokeWidth) {
o.strokeWidthUnscaled = o.strokeWidth;
}
if (o.strokeWidthUnscaled) {
o.strokeWidth = o.strokeWidthUnscaled / o.scaleX;
}
});
今私が欲しいのは、オブジェクトをスケーリングしている間、境界線の増加を防ぐことです。境界線は以前のままにする必要があります。
これがスニペットです/ Codepen
var canvas = new fabric.Canvas('canvas1');
$('.add_shape').click(function() {
var cur_value = $(this).attr('data-rel');
if (cur_value != '') {
switch (cur_value) {
case 'rectangle':
var rect = new fabric.Rect({
left: 50,
top: 50,
fill: '#aaa',
width: 50,
height: 50,
opacity: 1,
stroke: '#000',
strokeWidth: 1
});
canvas.add(rect);
canvas.setActiveObject(rect);
break;
case 'circle':
var circle = new fabric.Circle({
left: 50,
top: 50,
fill: '#aaa',
radius: 50,
opacity: 1,
stroke: '#000',
strokeWidth: 1
});
canvas.add(circle);
canvas.setActiveObject(circle);
break;
}
}
});
canvas.on('object:scaling', (e) => {
var o = e.target;
if (!o.strokeWidthUnscaled && o.strokeWidth) {
o.strokeWidthUnscaled = o.strokeWidth;
}
if (o.strokeWidthUnscaled) {
o.strokeWidth = o.strokeWidthUnscaled / o.scaleX;
}
});
/* Control the border */
$('#control_border').change(function() {
var cur_value = parseInt($(this).val());
var activeObj = canvas.getActiveObject();
if (activeObj == undefined) {
alert('Please select the Object');
return false;
}
activeObj.set({
strokeWidth: cur_value
});
canvas.renderAll();
});
button {
max-resolution: 10px;
height: 30px;
}
div {
margin: 10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.0-beta.7/fabric.js"></script>
<div>
<button class="add_shape" data-rel="circle">Add Circle</button>
<button class="add_shape" data-rel="rectangle">Add Rectangle</button>
<label class="control-label">Border</label>
<input id="control_border" type="range" min="0" max="10" step="1" value="0" />
</div>
<canvas id="canvas1" width="600" height="300" style="border:1px solid #000000;"></canvas>
1)長方形を追加します
2)境界線を適用します(たとえば5)
3)そのオブジェクトをスケーリングします
これで、適用された境界線がなくなったことがわかります。では、それをどのように解決するのでしょうか?
以下のオプションを試しましたが、機能しません。基本的に、長方形、円、三角形、線、多角形などのオブジェクトのストローク幅/境界線を維持しようとしています。
私がこれまでに試したこと:
//1st try
canvas.on('object:scaling', (e) => {
var o = e.target;
o.strokeWidth = o.strokeWidth / ((o.scaleX + o.scaleY) / 2);
var activeObject = canvas.getActiveObject();
activeObject.set('strokeWidth',o.strokeWidth);
});
//2nd try
canvas.on('object:scaling', (e) => {
if (!o.strokeWidthUnscaled && o.strokeWidth) {
o.strokeWidthUnscaled = o.strokeWidth;
}
if (o.strokeWidthUnscaled) {
o.strokeWidth = o.strokeWidthUnscaled / o.scaleX;
}
});
//3rd try
fabric.Object.prototype._renderStroke = function(ctx) {
if (!this.stroke || this.strokeWidth === 0) {
return;
}
if (this.shadow && !this.shadow.affectStroke) {
this._removeShadow(ctx);
}
ctx.save();
ctx.scale(1 / this.scaleX, 1 / this.scaleY);
this._setLineDash(ctx, this.strokeDashArray, this._renderDashedStroke);
this._applyPatternGradientTransform(ctx, this.stroke);
ctx.stroke();
ctx.restore();
};
https://github.com/kangax/fabric.js/issues/66
Fabricjsのグループの場合、サイズ変更中にstrokeWidthの厚さを維持できません
Fabricjsオブジェクトを拡大縮小するが、境界線(ストローク)の幅を固定する方法
境界線のサイズを維持するためにfabricjs rectのサイズを変更します
https://github.com/kangax/fabric.js/issues/2012
しかし、解決策を見つけることができません。
初めてstrokeWidth
をstrokeWidthUnscaled
に設定してから、スケーリングで@を設定します。キャッシュの場合は、変更後にスケーリングする場合にのみfalseにします。
object.strokeWidth = object.strokeWidthUnscaled/((object.scaleX+object.scaleY)/2);
そして、新しいストローク幅を選択するには、これを行います
var newStrokeWidth = cur_value / ((activeObj.scaleX + activeObj.scaleY) / 2)
activeObj.set({
strokeWidth: newStrokeWidth,
strokeWidthUnscaled : cur_value
});
例
var canvas = new fabric.Canvas('canvas1');
var globalStrokeWidth = 1;
$('.add_shape').click(function() {
var cur_value = $(this).attr('data-rel');
if (cur_value != '') {
switch (cur_value) {
case 'rectangle':
var rect = new fabric.Rect({
left: 50,
top: 50,
fill: '#aaa',
width: 50,
height: 50,
opacity: 1,
stroke: '#000',
strokeWidth: globalStrokeWidth
});
canvas.add(rect);
canvas.setActiveObject(rect);
break;
case 'circle':
var circle = new fabric.Circle({
left: 50,
top: 50,
fill: '#aaa',
radius: 50,
opacity: 1,
stroke: '#000',
strokeWidth: globalStrokeWidth
});
canvas.add(circle);
canvas.setActiveObject(circle);
break;
}
}
});
canvas.on('object:scaling', (e) => {
var o = e.target;
if (!o.strokeWidthUnscaled && o.strokeWidth) {
o.strokeWidthUnscaled = o.strokeWidth;
}
if (o.strokeWidthUnscaled) {
if(o.objectCaching) o.objectCaching = false;
o.strokeWidth = o.strokeWidthUnscaled / ((o.scaleX + o.scaleY) / 2);
}
});
canvas.on('object:modified', (e) => {
var o = e.target;
if(!o.objectCaching) o.objectCaching = true;
canvas.renderAll();
});
/* Control the border */
$('#control_border').change(function() {
var cur_value = parseInt($(this).val());
globalStrokeWidth = cur_value;
var activeObj = canvas.getActiveObject();
if (activeObj == undefined) {
alert('Please select the Object');
return false;
}
var newStrokeWidth = cur_value / ((activeObj.scaleX + activeObj.scaleY) / 2)
activeObj.set({
strokeWidth: newStrokeWidth,
strokeWidthUnscaled : cur_value
});
activeObj.setCoords();
canvas.renderAll();
});
button {
max-resolution: 10px;
height: 30px;
}
div {
margin: 10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.0-beta.7/fabric.js"></script>
<div>
<button class="add_shape" data-rel="circle">Add Circle</button>
<button class="add_shape" data-rel="rectangle">Add Rectangle</button>
<label class="control-label">Border</label>
<input id="control_border" type="range" min="0" max="10" step="1" value="0" />
</div>
<canvas id="canvas1" width="600" height="300" style="border:1px solid #000000;"></canvas>
これは、Fabric.jsバージョン2.7.0からはるかに簡単になりました。 strokeUniform
プロパティが追加されました。これを有効にすると、ストローク幅がオブジェクトのスケール値の影響を受けなくなります。
obj.set('strokeUniform', true);
https://github.com/fabricjs/fabric.js/pull/5546
var canvas = new fabric.Canvas('canvas1');
$('.add_shape').click(function() {
var cur_value = $(this).attr('data-rel');
if (cur_value != '') {
switch (cur_value) {
case 'rectangle':
var rect = new fabric.Rect({
left: 50,
top: 50,
fill: '#aaa',
width: 50,
height: 50,
opacity: 1,
stroke: '#000',
strokeWidth: 1,
noScaleCache: false,
strokeUniform: true,
});
canvas.add(rect);
canvas.setActiveObject(rect);
break;
case 'circle':
var circle = new fabric.Circle({
left: 50,
top: 50,
fill: '#aaa',
radius: 50,
opacity: 1,
stroke: '#000',
strokeWidth: 1,
noScaleCache: false,
strokeUniform: true
});
canvas.add(circle);
canvas.setActiveObject(circle);
break;
}
}
});
/* Control the border */
$('#control_border').change(function() {
var cur_value = parseInt($(this).val());
var activeObj = canvas.getActiveObject();
if (activeObj == undefined) {
alert('Please select the Object');
return false;
}
activeObj.set({
strokeWidth: cur_value
});
canvas.renderAll();
});
button {
max-resolution: 10px;
height: 30px;
}
div {
margin: 10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.min.js"></script>
<div>
<button class="add_shape" data-rel="circle">Add Circle</button>
<button class="add_shape" data-rel="rectangle">Add Rectangle</button>
<label class="control-label">Border</label>
<input id="control_border" type="range" min="0" max="10" step="1" value="0" />
</div>
<canvas id="canvas1" width="600" height="300" style="border:1px solid #000000;"></canvas>
この問題に取り組んでいるときに、幅と高さのオブジェクト値のサイズを変更しても変更されず、scaleXとscaleYのみが変更されることに気付きました。ストローク幅を維持するには、scaleXとscalyYを1にリセットし、幅と高さを新しい値で更新する必要があります。
長方形の場合:
var currObj = canvas.getActiveObject();
if (currObj.type === 'rect') {
var newWidth = currObj.width * currObj.scaleX,
newHeight = currObj.height * currObj.scaleY;
currObj.set({
'width': newWidth,
'height': newHeight,
scaleX: 1,
scaleY: 1
});
}
楕円の場合:
var currObj = canvas.getActiveObject();
if (currObj.type === 'ellipse') {
var newRX = currObj.rx * currObj.scaleX,
newRY = currObj.ry * currObj.scaleY;
currObj.set({
'rx': newRX,
'ry': newRY,
scaleX: 1,
scaleY: 1
});
}
後でcanvas.renderAll()を呼び出すことを忘れないでください。
Object:scalingで、スケールに基づいた計算をコメントアウトしました。スケーリングされていない値は= 1であり、スケーリングによって除算されたため、境界線は常に分数に等しくなりました(配置されたままではありません)。
var canvas = new fabric.Canvas('canvas1');
$('.add_shape').click(function() {
var cur_value = $(this).attr('data-rel');
if (cur_value != '') {
switch (cur_value) {
case 'rectangle':
var rect = new fabric.Rect({
left: 50,
top: 50,
fill: '#aaa',
width: 50,
height: 50,
opacity: 1,
stroke: '#000',
strokeWidth: 1
});
canvas.add(rect);
canvas.setActiveObject(rect);
break;
case 'circle':
var circle = new fabric.Circle({
left: 50,
top: 50,
fill: '#aaa',
radius: 50,
opacity: 1,
stroke: '#000',
strokeWidth: 1
});
canvas.add(circle);
canvas.setActiveObject(circle);
break;
}
}
});
canvas.on('object:scaling', (e) => {
var o = e.target;
if (!o.strokeWidthUnscaled && o.strokeWidth) {
o.strokeWidthUnscaled = o.strokeWidth;
}
if (o.strokeWidthUnscaled) {
//o.strokeWidth = o.strokeWidthUnscaled / o.scaleX;
}
});
/* Control the border */
$('#control_border').change(function() {
var cur_value = parseInt($(this).val());
var activeObj = canvas.getActiveObject();
if (activeObj == undefined) {
alert('Please select the Object');
return false;
}
activeObj.set({
strokeWidth: cur_value
});
canvas.renderAll();
});
button {
max-resolution: 10px;
height: 30px;
}
div {
margin: 10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.0-beta.7/fabric.js"></script>
<div>
<button class="add_shape" data-rel="circle">Add Circle</button>
<button class="add_shape" data-rel="rectangle">Add Rectangle</button>
<label class="control-label">Border</label>
<input id="control_border" type="range" min="0" max="10" step="1" value="0" />
</div>
<canvas id="canvas1" width="600" height="300" style="border:1px solid #000000;"></canvas>