Как сворачивать свою группу, чтобы поместиться на сцене, даже если группа состоит шире
Эта иллюстрация показывает, начиная «синий» группа - не расширен и не масштабируется.
Эта иллюстрация показывает синий группу после того, как он расширился за пределы сцены и масштабируется обратно.
Вот как сворачивать свою группу без нее «плавающим» слева:
- Отменить любую предыдущую группу смещение (на величину любого предыдущего коэффициента масштабирования).
- Рассчитать новый коэффициент масштабирования (например: уменьшить масштаб).
- Сохраните новый коэффициент масштабирования для использования в любом будущем масштабировании.
- Рассчитать новое смещение группы на основе нового коэффициента масштабирования.
- Установите смещение группы на недавно измененное смещение.
- Перерисовать слой.
Вам нужно будет добавить несколько свойств drawingGroup, связанные с масштабированием:
// the current SCALED offset
drawingGroup.offsetX=0;
drawingGroup.offsetY=0;
// the point from which all scaling will occur
drawingGroup.scalePtX=0;
drawingGroup.scalePtY=0;
// the amount of current scaling applied to the group
// ==1.00 is the beginning un-scaled group
// >1.00 scales the group larger
// <1.00 scales the group smaller
drawingGroup.scaleFactor=1.00;
Затем добавьте этот метод drawingGroup фактически сделать масштабирование:
drawingGroup.scaleBy=function(scaleChange){
// undo previous offset
this.offsetX += this.scalePtX/this.scaleFactor;
this.offsetY += this.scalePtY/this.scaleFactor;
// calc new scaling factor
var newScaleFactor = this.scaleFactor*(1+scaleChange);
// create new offset
this.offsetX -= this.scalePtX/newScaleFactor;
this.offsetY -= this.scalePtY/newScaleFactor;
// set new scale factor
this.scaleFactor=newScaleFactor;
// do the new offset
this.setOffset(this.offsetX,this.offsetY);
// do the new scale
this.setScale(this.scaleFactor);
layer.draw();
};
Это тестовый код, который оба расширяют группу и автоматически уменьшают ее, чтобы соответствовать этапу:
Этот тестовый код также заживает группу после downscal ING.
// widen by 20px
// if wider than stage, scale down by 15%
$("#wider").click(function(){
drawingGroup.setWidth(drawingGroup.getWidth()+20);
rect.setWidth(drawingGroup.getWidth());
var width=drawingGroup.getWidth()*drawingGroup.scaleFactor;
if(drawingGroup.getX()+width>stageWidth){
drawingGroup.scaleBy(-0.15);
recenter();
}
setStatus();
layer.draw();
});
function recenter(){
var w=drawingGroup.getWidth()*drawingGroup.scaleFactor;
var h=drawingGroup.getHeight()*drawingGroup.scaleFactor;
drawingGroup.setX(stage.getWidth()/2-w/2);
drawingGroup.setY(stage.getHeight()/2-h/2);
}
Обратите внимание, что setX()/setY() может использоваться обычно для группы.
Просто не забудьте рассчитать шкалу ширину/высоту группы путем умножения на scalingFactor.
Вот полный код и скрипку: http://jsfiddle.net/m1erickson/UyDbW/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.4.min.js"></script>
<style>
body{ padding:15px; }
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:300px;
height:300px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
stage.add(layer);
// objects used in jquery events
var drawingGroup;
var rect,circle;
var stageWidth=stage.getWidth();
var stageHeight=stage.getHeight();
drawingGroup=new Kinetic.Group({
x:stageWidth/2-50,
y:stageHeight/2-50,
width:100,
height:100,
});
drawingGroup.offsetX=0;
drawingGroup.offsetY=0;
drawingGroup.scalePtX=0;
drawingGroup.scalePtY=0;
drawingGroup.scaleFactor=1.00;
drawingGroup.scaleBy=function(scaleChange){
// undo previous offset
this.offsetX += this.scalePtX/this.scaleFactor;
this.offsetY += this.scalePtY/this.scaleFactor;
// calc new scaling factor
var newScaleFactor = this.scaleFactor*(1+scaleChange);
// create new offset
this.offsetX -= this.scalePtX/newScaleFactor;
this.offsetY -= this.scalePtY/newScaleFactor;
// set new scale factor
this.scaleFactor=newScaleFactor;
// do the new offset
this.setOffset(this.offsetX,this.offsetY);
// do the new scale
this.setScale(this.scaleFactor);
layer.draw();
};
layer.add(drawingGroup);
var rect=new Kinetic.Rect({
x:0,
y:0,
width:100,
height:100,
stroke:"lightgray",
fill:"skyblue"
});
drawingGroup.add(rect);
var circle=new Kinetic.Circle({
x:50,
y:50,
radius:20,
fill:"blue"
});
drawingGroup.add(circle);
var status=new Kinetic.Text({
x:15,
y:15,
text:"width=100, scale=1.00",
fontSize:18,
fill:"red"
});
layer.add(status);
setStatus();
layer.draw();
function setStatus(){
var width=drawingGroup.getWidth();
var scale=Math.round(drawingGroup.scaleFactor*100);
status.setText("Width: "+width+", Scale: "+scale+"%");
}
// widen by 20px
// if wider than stage, scale down by 15%
$("#wider").click(function(){
drawingGroup.setWidth(drawingGroup.getWidth()+20);
rect.setWidth(drawingGroup.getWidth());
var width=drawingGroup.getWidth()*drawingGroup.scaleFactor;
if(drawingGroup.getX()+width>stageWidth){
drawingGroup.scaleBy(-0.15);
recenter();
}
setStatus();
layer.draw();
});
function recenter(){
var w=drawingGroup.getWidth()*drawingGroup.scaleFactor;
var h=drawingGroup.getHeight()*drawingGroup.scaleFactor;
drawingGroup.setX(stage.getWidth()/2-w/2);
drawingGroup.setY(stage.getHeight()/2-h/2);
}
}); // end $(function(){});
</script>
</head>
<body>
<p>Blue group will scale if extending past stage</p>
<button id="wider">Wider</button>
<div id="container"></div>
</body>
</html>
Это близко к тому, что я ищу. Разница в том, что каждый раз, когда длина группы рисования расширяется, я пытаюсь обновить изображение внутри слоя, когда оно будет перерисовано. Знаете ли вы хороший способ сделать это? – Tom
Я отредактировал свой ответ, чтобы повторно включить группу после того, как она была уменьшена. Обратите внимание, что вы можете использовать setX/setY обычно в группе. Тем не менее, getWidth/getHeight будет сообщать о немасштабированных значениях, поэтому вы должны умножить эту ширину/высоту с помощью scaleFactor drawingGroup, чтобы получить масштабированные размеры. – markE
У меня есть обновление по этому вопросу. То, что я хотел бы сделать, - отрегулировать длину чертежа и масштабировать чертеж с каждым шагом. Я хотел бы, чтобы рисунок был центрирован по оси y, но рисунок должен быть установлен на 20 пикселей с левой стороны сцены. Я не смог правильно настроить масштабирование при использовании increment/decment. Есть ли способ заставить это работать? – Tom