I'm making a 3D box with Zdog and I want to let the height of the box grow.
Here is a codepen: https://codepen.io/anon/pen/qzBMgp.
This is my code for the box:
let progressBox = new Zdog.Box({
addTo: progress,
width: 200,
height: boxHeight,
depth: 200,
stroke: 1,
})
This is the code I use to increase the height of the box. If the box is shorter than 400, the box will increase its height with 0.1.
function animate() {
if (boxHeight < 400) {
moveUp = 'up';
} else if (boxHeight > 400) {
moveUp = 'false';
}
boxHeight += moveUp == 'up' ? 0.1 : 0;
}
The problem is that the box stays at a height of 0 (the value I gave to boxHeight), but when I console.log(boxHeight) the boxHeight will grow.
First of all, let me point out that you cannot change the value of a constant . On your code, the boxHeight is declared as const.
Second, you will need to use Zdog's copy() method. Here is your code modified accordingly.
Zdog.Anchor.prototype.renderGraphSvg = function (svg) {
if (!svg) {
throw new Error('svg is ' + svg + '. ' +
'SVG required for render. Check .renderGraphSvg( svg ).');
}
this.flatGraph.forEach(function (item) {
item.render(svg, Zdog.SvgRenderer);
});
};
const TAU = Zdog.TAU;
const light = '#EAE2B7';
const yellow1 = '#FCBF49';
const orange1 = '#F77F00';
const red1 = '#d62828';
const purple1 = '#003049';
const white1 = '#ffffff';
const isSpinning = true;
var boxHeight = 0;
let progress = new Zdog.Illustration({
element: '.progress',
dragRotate: true,
translate: {
y: 25
},
rotate: {
x: -0.4, y: 0.75
}
});
let progressBox = new Zdog.Box({
addTo: progress,
width: 200,
depth: 200,
height: boxHeight,
stroke: 1,
color: purple1, // default face color
leftFace: yellow1,
rightFace: orange1,
topFace: red1,
bottomFace: light,
translate: {
x: 0,
y: 300
},
});
function animate() {
if (boxHeight <= 400) {
boxHeight++; // 1
progressBox = progressBox.copy({
height: boxHeight, // overwrite height
translate: {
y: progressBox.translate.y - 1 // overwrite vertical position to put box in place while height is growing.
}
});
}
progress.updateRenderGraph();
requestAnimationFrame(animate);
}
animate();
I forked your pen and updated it with the code above. See Zdog - progress box
Note that it seems to be expensive doing the copy() method on every animation frame. I am also new to this library and this is currently the fix I know of.
Related
I am having problem trying to make a spinning wheel spin automatically on page load and also display multiple wheels on the same page. The spinner is based on Phaser. I am not a JavaScript nor Phaser programmer so your assistance is appreciated. This is probably something simple to do.
Here is the game.js code for the spinning wheel. (The complete spinning wheel script can be downloaded here)
// the game itself
var game;
var gameOptions = {
// slices (prizes) placed in the wheel
slices: 8,
// prize names, starting from 12 o'clock going clockwise
slicePrizes: ["A KEY!!!", "50 STARS", "500 STARS", "BAD LUCK!!!", "200 STARS", "100 STARS", "150 STARS", "BAD LUCK!!!"],
// wheel rotation duration, in milliseconds
rotationTime: 3000
}
// once the window loads...
window.onload = function() {
// game configuration object
var gameConfig = {
// render type
type: Phaser.CANVAS,
// game width, in pixels
width: 550,
// game height, in pixels
height: 550,
// game background color
backgroundColor: 0x880044,
// scenes used by the game
scene: [playGame]
};
// game constructor
game = new Phaser.Game(gameConfig);
// pure javascript to give focus to the page/frame and scale the game
window.focus()
resize();
window.addEventListener("resize", resize, false);
}
// PlayGame scene
class playGame extends Phaser.Scene{
// constructor
constructor(){
super("PlayGame");
}
// method to be executed when the scene preloads
preload(){
// loading assets
this.load.image("wheel", "wheel.png");
this.load.image("pin", "pin.png");
}
// method to be executed once the scene has been created
create(){
// adding the wheel in the middle of the canvas
this.wheel = this.add.sprite(game.config.width / 2, game.config.height / 2, "wheel");
// adding the pin in the middle of the canvas
this.pin = this.add.sprite(game.config.width / 2, game.config.height / 2, "pin");
// adding the text field
this.prizeText = this.add.text(game.config.width / 2, game.config.height - 20, "Spin the wheel", {
font: "bold 32px Arial",
align: "center",
color: "white"
});
// center the text
this.prizeText.setOrigin(0.5);
// the game has just started = we can spin the wheel
this.canSpin = true;
// waiting for your input, then calling "spinWheel" function
this.input.on("pointerdown", this.spinWheel, this);
}
// function to spin the wheel
spinWheel(){
// can we spin the wheel?
if(this.canSpin){
// resetting text field
this.prizeText.setText("");
// the wheel will spin round from 2 to 4 times. This is just coreography
var rounds = Phaser.Math.Between(2, 4);
// then will rotate by a random number from 0 to 360 degrees. This is the actual spin
var degrees = Phaser.Math.Between(0, 360);
// before the wheel ends spinning, we already know the prize according to "degrees" rotation and the number of slices
var prize = gameOptions.slices - 1 - Math.floor(degrees / (360 / gameOptions.slices));
// now the wheel cannot spin because it's already spinning
this.canSpin = false;
// animation tweeen for the spin: duration 3s, will rotate by (360 * rounds + degrees) degrees
// the quadratic easing will simulate friction
this.tweens.add({
// adding the wheel to tween targets
targets: [this.wheel],
// angle destination
angle: 360 * rounds + degrees,
// tween duration
duration: gameOptions.rotationTime,
// tween easing
ease: "Cubic.easeOut",
// callback scope
callbackScope: this,
// function to be executed once the tween has been completed
onComplete: function(tween){
// displaying prize text
this.prizeText.setText(gameOptions.slicePrizes[prize]);
// player can spin again
this.canSpin = true;
}
});
}
}
}
// pure javascript to scale the game
function resize() {
var canvas = document.querySelector("canvas");
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var windowRatio = windowWidth / windowHeight;
var gameRatio = game.config.width / game.config.height;
if(windowRatio < gameRatio){
canvas.style.width = windowWidth + "px";
canvas.style.height = (windowWidth / gameRatio) + "px";
}
else{
canvas.style.width = (windowHeight * gameRatio) + "px";
canvas.style.height = windowHeight + "px";
}
}
Does anyone know how to make it so that
it will start spinning as soon as the page is loaded.
place more than one wheel on a page. When I call the JavaScript twice, it does not display two wheels. The purpose of this exercise is to feed the wheel with two different "degrees" so that it can display the two results. The alternative will be to spin the wheel twice. After the first spin, display the first result and spin again to display the second result. But this is probably harder to do than simply display two wheels.
Thanks in advance.
For the first part of your question , '...spinning as soon as page is loaded..', the answer is:
just add the code line this.spinWheel(); at the end of the create function, this will start it right away.
For the second part:
just add in the gameConfig - object the property parent, with an id of an html-tag
create a game instance (no action needed)
than copy and past the whole gameConfig
change the parent, to a different tag-id
create a second game instance. ( add the line game = new Phaser.Game(gameConfig);)
Here a short Demo showcasing, these two fixes:
(depending on your exact goal, and what you want to achieve, there might be better ways to solve this)
FYI:
Images are not loaded, because they won't work here, but one can see how the auto spinning would work.
I remove code that was not so relevant for the demo, so that it can be understund more easy.
document.body.style = 'margin:0;';
var gameOptions = {
slices: 8,
slicePrizes: ["A KEY!!!", "50 STARS", "500 STARS", "BAD LUCK!!!", "200 STARS", "100 STARS", "150 STARS", "BAD LUCK!!!"],
rotationTime: 3000
}
class playGame extends Phaser.Scene{
constructor(){
super("PlayGame");
}
preload(){
//this.load.image("wheel", "wheel.png");
//this.load.image("pin", "pin.png");
}
create(){
this.wheel = this.add.sprite(game.config.width / 2, game.config.height / 2, "wheel");
this.pin = this.add.sprite(game.config.width / 2, game.config.height / 2, "pin");
this.prizeText = this.add.text(game.config.width / 2, game.config.height - 20, "Spin the wheel", {
font: "bold 32px Arial",
align: "center",
color: "white"
});
this.prizeText.setOrigin(0.5);
this.canSpin = true;
this.input.on("pointerdown", this.spinWheel, this);
this.spinWheel();
}
spinWheel(){
if(this.canSpin){
this.prizeText.setText("");
var rounds = Phaser.Math.Between(2, 4);
var degrees = Phaser.Math.Between(0, 360);
var prize = gameOptions.slices - 1 - Math.floor(degrees / (360 / gameOptions.slices));
this.canSpin = false;
this.tweens.add({
targets: [this.wheel],
angle: 360 * rounds + degrees,
duration: gameOptions.rotationTime,
ease: "Cubic.easeOut",
callbackScope: this,
onComplete: function(tween){
this.prizeText.setText(gameOptions.slicePrizes[prize]);
this.canSpin = true;
}
});
}
}
}
var gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel1',
width: 200,
height: 200,
backgroundColor: 0x880044,
scene: [playGame]
};
var game = new Phaser.Game(gameConfig);
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel2',
width: 200,
height: 200,
// I altered also the background color to show the difference
backgroundColor: 0x0ff044,
scene: [playGame]
};
game = new Phaser.Game(gameConfig);
#wheel1, #wheel2, canvas{
display:inline-block;
padding:0;
margin:0;
}
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
<div id="wheel1"></div><div id="wheel2"></div>
Updated - Update:
The main problem is that I made a mistake, the property is not parentElement it is parent. I tried to fix this in following demo.
// the game itself
var game;
var gameOptions = {
// slices (prizes) placed in the wheel
slices: 8,
// prize names, starting from 12 o'clock going clockwise
// this array has to contain atleast 8 value
slicePrizes: ["A KEY!!!", "50 STARS", "500 STARS", "BAD LUCK!!!", "200 STARS", "100 STARS", "150 STARS", "BAD LUCK!!!"],
// wheel rotation duration, in milliseconds
rotationTime: 3000
}
var gameConfig;
// once the window loads...
window.onload = function () {
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel1',
width: 200,
height: 200,
backgroundColor: 0x880044,
scene: [playGame]
};
var game = new Phaser.Game(gameConfig);
game.scene.start('PlayGame', { degrees: 60 });
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel2',
width: 200,
height: 200,
// I altered also the background color to show the difference
backgroundColor: 0x0ff044,
scene: [playGame]
};
var game2 = new Phaser.Game(gameConfig);
game2.scene.start('PlayGame', { degrees: 40 });
window.focus()
resize();
window.addEventListener("resize", resize, false);
}
// PlayGame scene
class playGame extends Phaser.Scene {
// constructor
constructor() {
super({ key: "PlayGame" });
}
// method to be executed when the scene preloads
preload() {
// loading assets
//this.load.image("wheel", "wheel.png");
//this.load.image("pin", "pin.png");
}
// method to be executed once the scene has been created
create(data) {
// adding the wheel in the middle of the canvas
this.wheel = this.add.sprite(gameConfig.width / 2, gameConfig.height / 2, "wheel");
// adding the pin in the middle of the canvas
this.pin = this.add.sprite(gameConfig.width / 2, gameConfig.height / 2, "pin");
// adding the text field
this.prizeText = this.add.text(gameConfig.width / 2, gameConfig.height - 20, "Spin the wheel", {
font: "bold 32px Arial",
align: "center",
color: "black"
});
// center the text
this.prizeText.setOrigin(0.5);
// the game has just started = we can spin the wheel
this.canSpin = true;
//this.input.on("pointerdown", this.spinWheel, this);
this.spinWheel(data.degrees);
}
// function to spin the wheel
spinWheel(degrees) {
// can we spin the wheel?
if (this.canSpin) {
// resetting text field
this.prizeText.setText("");
// the wheel will spin round from 2 to 4 times. This is just coreography
var rounds = Phaser.Math.Between(8, 10);
//var degrees = Phaser.Math.Between(0, 360);
var prize = gameOptions.slices - 1 - Math.floor(degrees / (360 / gameOptions.slices));
// now the wheel cannot spin because it's already spinning
this.canSpin = false;
// animation tweeen for the spin: duration 3s, will rotate by (360 * rounds + degrees) degrees
// the quadratic easing will simulate friction
this.tweens.add({
// adding the wheel to tween targets
targets: [this.wheel],
// angle destination
angle: 360 * rounds + degrees,
// tween duration
duration: gameOptions.rotationTime,
// tween easing
ease: "Cubic.easeOut",
// callback scope
callbackScope: this,
// function to be executed once the tween has been completed
onComplete: function (tween) {
// displaying prize text
this.prizeText.setText(gameOptions.slicePrizes[prize]);
// player can spin again
this.canSpin = true;
}
});
}
}
}
// pure javascript to scale the game
function resize() {
var canvas = document.querySelector("#wheels");
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var windowRatio = windowWidth / windowHeight;
var gameRatio = gameConfig.width / gameConfig.height;
if (windowRatio < gameRatio) {
canvas.style.width = windowWidth + "px";
//canvas.style.height = (windowWidth / gameRatio) + "px";
}
else {
canvas.style.width = (windowHeight * gameRatio) + "px";
//canvas.style.height = windowHeight + "px";
}
}
body{
padding: 0px;
margin: 0px;
}
#wheels{
display: flex;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
align-items: stretch;
}
#wheel1, #wheel2, canvas{
flex-grow: 1;
margin: 0;
padding: 0;
}
canvas{
width: 100%;
}
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
<div id="wheels">
<div id="wheel1"></div>
<div id="wheel2"></div>
</div>
I'm using fabricjs to make a ruler tool. When the user click on the canvas it will draw a small rectangle and a line (with length of 0) as the user starts to move the mouse the length of line increases. At the top of the line There's a text which will show the length of the line. The length of the line is updating But it won't display the updated length. It displays the updated length once I click again to finish drawing.
Here's my code
let oneSideDrawn = false;
canvas.on("mouse:down", (event) => {
function rulerDown() {
const mouse = canvas.getPointer(event.e);
const { x, y } = mouse;
const side = new fabric.Rect({
width: 3,
height: 16,
left: x,
top: y,
fill: "#222",
});
canvas.add(side);
updateCanvas();
if (oneSideDrawn) {
oneSideDrawn = false;
const objs = canvas.getObjects();
const length = objs.length;
const line = objs[length - 3];
const side2 = objs[length - 4];
side.set({ top: side2.top });
const txt = canvas.getById("myId");
const rulerGroup = new fabric.Group([side2, line, side, txt], {
basicStyle,
lockScalingX: true,
lockScalingY: true,
});
canvas.add(rulerGroup);
canvas.remove(side2);
canvas.remove(line);
canvas.remove(side);
canvas.remove(txt);
canvas.setActiveObject(rulerGroup);
updateCanvas();
updateMode("");
} else {
const line = new fabric.Rect({
width: 0,
height: 3,
left: x,
top: y + 6,
fill: "#222",
});
const txt = new fabric.Text("0 m", {
fontSize: 10,
left: line.left + line.width / 2,
top: side.top - 5,
id: "myId",
});
txt.set({ left: txt.left - txt.width / 2 });
canvas.add(line);
canvas.add(txt);
updateCanvas();
canvas.setActiveObject(line);
oneSideDrawn = true;
}
}
}
canvas.on("mouse:move", (event) => {
function rulerMove() {
const line = canvas.getActiveObject();
const lineTxt = canvas.getById("myId");
const mouse = canvas.getPointer(event.e);
const { x } = mouse;
const width = Math.abs(x - line.left);
if (!width) {
return false;
}
line.set({ width });
lineTxt.set({
text: parseFloat(width).toFixed(2) + " m",
left: line.left + width / 2 - 15,
});
updateCanvas();
}
}
Here's a screen shot
As we can see the text is updating in the console.log But the value is still "0 m" on the canvas
Update fabricjs!
I was facing this issue when I was using fabricjs 4.3.0.
In fabricjs 4.4.0 they solved this issue
Hi I'm using konva js (https://konvajs.org) with vue and I'm trying to animate the text so that it slides into the screen from off the stage to a certain position, however I'm not 100% sure how this should work, I've been able to get a demo working here;
https://codesandbox.io/s/vue-konva-template-i2em3
Vue;
<v-stage ref="stage" :config="stageSize">
<v-layer ref="layer">
<v-text
ref="text1"
:config="{
text: 'Draggable Text',
x: 50,
y: 50,
draggable: true,
fill: 'black'
}"
/>
</v-layer>
</v-stage>
</template>
<script>
const width = window.innerWidth;
const height = window.innerHeight;
export default {
data() {
return {
stageSize: {
width: width,
height: height
}
};
},
methods: {
changeSize(e) {
// to() is a method of `Konva.Node` instances
e.target.to({
scaleX: Math.random() + 0.8,
scaleY: Math.random() + 0.8,
duration: 0.2
});
}
},
mounted() {
const vm = this;
const amplitude = 100;
const period = 5000;
// in ms
const centerX = vm.$refs.stage.getStage().getWidth() / 2;
const text = this.$refs.text1.getStage();
// example of Konva.Animation
const anim = new Konva.Animation(function(frame) {
text.setX(
amplitude * Math.sin((frame.time * 2 * Math.PI) / period) + centerX
);
}, text.getLayer());
anim.start();
}
};
</script>
any ideas how I can get the text to appear from outside of the stage and then stop at a certain point within the canvas?
You can just use node.to() method to animatio any Konva.Node:
mounted() {
const textNode = this.$refs.text1.getNode();
const endX = width / 2 - textNode.width() / 2;
// run the animation
textNode.to({
x: endX,
onFinish: () => {
// update the state at the end
this.textPos.x = endX;
}
})
}
Demo: https://codesandbox.io/s/vue-konva-animation-demo-lr4qw
See my example: https://jsfiddle.net/ksumarine/x7f9yLb7/4/
I have a .Stage that has an offset which puts 0, 0 at the bottom center of the canvas. This has a .Layer which draws the .Shape of an objects path from an array of x,y coordinates.
let routes = [{x: #, y: #}, {x: #, y: #}, ......] // example routes
let testStage = new Konva.Stage({
container: con,
x: 0,
y: 0,
width: 300,
height: 300,
offsetX: ((300 / 2) * -1),
offsetY: (300 * -1)
});
let testLayer = new Konva.Layer();
let testShape = new Konva.Shape({
sceneFunc: function(context) {
context.beginPath();
for (var i = 0; i < routes.length - 1; i++) {
context.moveTo(routes[i].x, routes[i].y);
context.lineTo(routes[i + 1].x, routes[i + 1].y);
}
context.strokeStyle = '#000';
context.lineWidth = 1.5;
context.stroke();
}
});
testLayer.add(testShape);
testStage.add(testLayer);
//////////// here's the button click event
animateButton.addEventListener('click', e => {
let i = 0;
let _ctx = testLayer.getContext()._context;
let draw = () => {
setTimeout(() => {
if (routes.length) {
_ctx.clearRect(0, 0, 300, 300);
_ctx.beginPath();
_ctx.moveTo(routes[0].x, (routes[0].y * -1));
for (let p = 1, plen = i; p < plen; p++) {
_ctx.lineTo(routes[p].x, (routes[p].y * -1));
}
_ctx.strokeStyle = '#000';
_ctx.lineWidth = 1.5;
_ctx.stroke();
(i === routes.length - 1) ? i = 0: i++;
}
requestAnimationFrame(draw);
}, 1000 / 59.940);
}
draw();
});
Everything at this point works well and the path is drawn as expected. I would like to use Konva.Animation to show how the object moved, but I cannot figure it out or find any examples to help.
I've added normal Canvas JS in the button eventListener as an example of the desired effect, but using the testLayer context to draw with puts 0,0 back at the top left...not what I want.
Could someone point me in the right direction to accomplish this using Konva.Animation?
For those coming across this question it was asked again in Nov 18, and this time there are two answers. See them here
I gone through documentation of cropper by fengyuanchen. I want the image to be fit by default into canvas if rotated. But I couldnt find a way to achieve this. Any idea how to achieve this functionality?
I want it to be like this to be default: link
Check issue demo here: link
I fixed this behavior but for my special needs. I just needed one rotate button which rotates an image in 90° steps. For other purposes you might extend/change my fix.
It works in "strict" mode by dynamically change the cropbox dimensions.
Here my function which is called, when I want to rotate an image. Ah and additionally the misplacement bug has also been fixed.
var $image;
function initCropper() {
$image = $('.imageUploadPreviewWrap > img').cropper({
autoCrop : true,
strict: true,
background: true,
autoCropArea: 1,
crop: function(e) {
}
});
}
function rotateImage() {
//get data
var data = $image.cropper('getCropBoxData');
var contData = $image.cropper('getContainerData');
var imageData = $image.cropper('getImageData');
//set data of cropbox to avoid unwanted behavior due to strict mode
data.width = 2;
data.height = 2;
data.top = 0;
var leftNew = (contData.width / 2) - 1;
data.left = leftNew;
$image.cropper('setCropBoxData',data);
//rotate
$image.cropper('rotate', 90);
//get canvas data
var canvData = $image.cropper('getCanvasData');
//calculate new height and width based on the container dimensions
var heightOld = canvData.height;
var heightNew = contData.height;
var koef = heightNew / heightOld;
var widthNew = canvData.width * koef;
canvData.height = heightNew;
canvData.width = widthNew;
canvData.top = 0;
if (canvData.width >= contData.width) {
canvData.left = 0;
}
else {
canvData.left = (contData.width - canvData.width) / 2;
}
$image.cropper('setCanvasData', canvData);
//and now set cropper "back" to full crop
data.left = 0;
data.top = 0;
data.width = canvData.width;
data.height = canvData.height;
$image.cropper('setCropBoxData',data);
}
This is my extended code provided by AlexanderZ to avoid cuttong wider images than container :)
var contData = $image.cropper('getContainerData');
$image.cropper('setCropBoxData',{
width: 2, height: 2, top: (contData.height/ 2) - 1, left: (contData.width / 2) - 1
});
$image.cropper('rotate', 90);
var canvData = $image.cropper('getCanvasData');
var newWidth = canvData.width * (contData.height / canvData.height);
if (newWidth >= contData.width) {
var newHeight = canvData.height * (contData.width / canvData.width);
var newCanvData = {
height: newHeight,
width: contData.width,
top: (contData.height - newHeight) / 2,
left: 0
};
} else {
var newCanvData = {
height: contData.height,
width: newWidth,
top: 0,
left: (contData.width - newWidth) / 2
};
}
$image.cropper('setCanvasData', newCanvData);
$image.cropper('setCropBoxData', newCanvData);
Not a direct answer to the question ... but i'm betting many people that use this plugin will find this helpfull..
Made this after picking up #AlexanderZ code to rotate the image.
So ... If you guys want to ROTATE or FLIP a image that has already a crop box defined and if you want that cropbox to rotate or flip with the image ... use these functions:
function flipImage(r, data) {
var old_cbox = $image.cropper('getCropBoxData');
var new_cbox = $image.cropper('getCropBoxData');
var canv = $image.cropper('getCanvasData');
if (data.method == "scaleX") {
if (old_cbox.left == canv.left) {
new_cbox.left = canv.left + canv.width - old_cbox.width;
} else {
new_cbox.left = 2 * canv.left + canv.width - old_cbox.left - old_cbox.width;
}
} else {
new_cbox.top = canv.height - old_cbox.top - old_cbox.height;
}
$image.cropper('setCropBoxData', new_cbox);
/* BUG: When rotated to a perpendicular position of the original position , the user perceived axis are now inverted.
Try it yourself: GO to the demo page, rotate 90 degrees then try to flip X axis, you'll notice the image flippped vertically ... but still ... it fliped in relation to its original axis*/
if ( r == 90 || r == 270 || r == -90 || r == -270 ) {
if ( data.method == "scaleX") {
$image.cropper("scaleY", data.option);
} else {
$image.cropper("scaleX", data.option);
}
} else {
$image.cropper(data.method, data.option);
}
$image.cropper(data.method, data.option);
}
function rotateImage(rotate) {
/* var img = $image.cropper('getImageData'); */
var old_cbox = $image.cropper('getCropBoxData');
var new_cbox = $image.cropper('getCropBoxData');
var old_canv = $image.cropper('getCanvasData');
var old_cont = $image.cropper('getContainerData');
$image.cropper('rotate', rotate);
var new_canv = $image.cropper('getCanvasData');
//calculate new height and width based on the container dimensions
var heightOld = new_canv.height;
var widthOld = new_canv.width;
var heightNew = old_cont.height;
var racio = heightNew / heightOld;
var widthNew = new_canv.width * racio;
new_canv.height = Math.round(heightNew);
new_canv.width = Math.round(widthNew);
new_canv.top = 0;
if (new_canv.width >= old_cont.width) {
new_canv.left = 0;
} else {
new_canv.left = Math.round((old_cont.width - new_canv.width) / 2);
}
$image.cropper('setCanvasData', new_canv);
if (rotate == 90) {
new_cbox.height = racio * old_cbox.width;
new_cbox.width = racio * old_cbox.height;
new_cbox.top = new_canv.top + racio * (old_cbox.left - old_canv.left);
new_cbox.left = new_canv.left + racio * (old_canv.height - old_cbox.height - old_cbox.top);
}
new_cbox.width = Math.round(new_cbox.width);
new_cbox.height = Math.round(new_cbox.height);
new_cbox.top = Math.round(new_cbox.top);
new_cbox.left = Math.round(new_cbox.left);
$image.cropper('setCropBoxData', new_cbox);
}
var photoToEdit = $('.photo_container img');
$( photoToEdit ).cropper({
autoCrop : true,
crop: function(e) {}
});
$("#rotate_left_btn").click( function () {
$( photoToEdit ).cropper('rotate', -90);
var containerHeightFactor = $(".photo_container").height() / $( photoToEdit).cropper('getCanvasData').height;
if ( containerHeightFactor < 1 ) { // if canvas height is greater than the photo container height, then scale (on both x and y
// axes to maintain aspect ratio) to make canvas height fit container height
$( photoToEdit).cropper('scale', containerHeightFactor, containerHeightFactor);
} else if ( $( photoToEdit).cropper('getData').scaleX != 1 || $( photoToEdit).cropper('getData').scaleY != 1 ) { // if canvas height
// is NOT greater than container height but image is already scaled, then revert the scaling cuz the current rotation will bring
// the image back to its original orientation (landscape/portrait)
$( photoToEdit).cropper('scale', 1, 1);
}
}
I Fixed this issue hope fully. i have added or changed the option to 0 (viewMode: 0,). Now its working well.
cropper = new Cropper(image, {
dragMode: 'none',
viewMode: 0,
width: 400,
height: 500,
zoomable: true,
rotatable: true,
crop: function(e) {
}
});
document.getElementById('rotateImg').addEventListener('click', function () {
cropper.rotate(90);
});