I use KineticJs and want to crop an existing image. I tried the following:
var image = new Kinetic.Image({}); // some kinetic image
var layer = new Kinetic.Layer();
var stage = new Kinetic.Stage({
container: "iPhone",
width: 1000,
height: 1000
});
image.crop({
x: 0,
y : 0,
width : 100,
height : 100
});
image = image.crop();
layer.add(image);
layer.draw();
stage.add(layer);
The former does not work. How do I crop an existing image with KineticJs?
You should pass javascript object with x, y, width and height properties to crop function:
image.crop({
x: 10,
y : 10,
width : 66,
height : 60
});
http://jsbin.com/zubek/2/edit
Related
I have a problem with fabric.js. I can use fabric.version, but after new fabric.Rect{top : 100,left : 100,width : 120,height : 30, fill : 'red'} and use canvas .add it, the rect not show but mouseEvent is ok.
my fabric.js version is 3.4.0
#angular/core": "~7.2.0","fabric": "^3.4.0"
ngOnInit() {
let canva1 = new fabric.Canvas('myCanvas');
console.log(fabric.version);
let rect = new fabric.Rect({
top : 100,
left : 100,
width : 120,
height : 30,
fill : 'red'
});
canva1.add(rect);
}
I expect a rect show on the canvas but no rect show
You have style="background: white" on your canvas element and it just blends with the background.
https://github.com/zhangManGod/canvas/blob/master/src/app/right/right.component.html#L3
Unless you have created your canvas with renderOnAddRemove = true (http://fabricjs.com/docs/fabric.Canvas.html#renderOnAddRemove) then you will need to call requestRenderAll on your canvas after you have added or removed items(s).
(http://fabricjs.com/docs/fabric.Canvas.html#requestRenderAll)
ngOnInit()
{
let canva1 = new fabric.Canvas('myCanvas');
console.log(fabric.version);
let rect = new fabric.Rect(
{
top : 100,
left : 100,
width : 120,
height : 30,
fill : 'red'
});
canva1.add(rect);
canva1.requestRenderAll()
}
I use Kinetic Sprite like this
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
var blob = new Kinetic.Sprite({
x: 250,
y: 40,
image: imageObj,
animation: 'idle',
animations: {
idle: [
// x, y, width, height (4 frames)
2,2,70,119,
71,2,74,119,
146,2,81,119,
226,2,76,119
],
punch: [
// x, y, width, height (3 frames)
2,138,74,122,
76,138,84,122,
346,138,120,122
]
},
frameRate: 7,
frameIndex: 0
});
// add the shape to the layer
layer.add(blob);
// add the layer to the stage
stage.add(layer);
// start sprite animation
blob.start();
var frameCount = 0;
blob.on('frameIndexChange', function(evt) {
if (blob.animation() === 'punch' && ++frameCount > 3) {
blob.animation('idle');
frameCount = 0;
}
});
document.getElementById('punch').addEventListener('click', function() {
alert("blob.width: "+blob.width());
}, false);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/blob-sprite.png';
The problem is that when using a sprite on mobile phone I get very poor drag performance. It is very slow to move or resize the sprite.
Is there a way to increase drag performance?
Edit: Here is an example with a Kinetic Image where dragging is very slow in Chrome for Android: http://jsfiddle.net/confile/brecmjzt/
Your performance problem is not the drag operation.
Refactor your code to not use frameIndexChange because it's extremely expensive to do a callback upon every sprite animation loop.
I loaded a sprite from a URL and wanted to get the width and height of the sprite it turns out that the width and height is alway zero. I created the following example.
How do I get the real width and height of the sprite?
I use the sprite example and created a jsfiddle here: http://jsfiddle.net/confile/jVG9t/
This is the html code:
<div id="container"></div>
<div id="buttons">
<input type="button" id="punch" value="Width">
</div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.1.0.min.js"></script>
Image <br>
<div id="mydiv" ></div>
This is the JS code:
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
var blob = new Kinetic.Sprite({
x: 250,
y: 40,
image: imageObj,
animation: 'idle',
animations: {
idle: [
// x, y, width, height (4 frames)
2,2,70,119,
71,2,74,119,
146,2,81,119,
226,2,76,119
],
punch: [
// x, y, width, height (3 frames)
2,138,74,122,
76,138,84,122,
346,138,120,122
]
},
frameRate: 7,
frameIndex: 0
});
// add the shape to the layer
layer.add(blob);
// add the layer to the stage
stage.add(layer);
// start sprite animation
blob.start();
var frameCount = 0;
blob.on('frameIndexChange', function(evt) {
if (blob.animation() === 'punch' && ++frameCount > 3) {
blob.animation('idle');
frameCount = 0;
}
});
document.getElementById('punch').addEventListener('click', function() {
alert("blob.width: "+blob.width());
}, false);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/blob-sprite.png';
You can get the width/height of the whole imageObj by requesting its .width & .height properties:
var imageObj = new Image();
imageObj.onload = function() {
var width=imageObj.width;
var height=imageObj.height;
}
If the imageObj is a spritesheet then there is no way to programatically get the x, y, width, height of the individual sprites on that spritesheet. Often the spritesheet author will give you this information. You can often eyeball the spritesheet and see how its laid out.
Your KineticJS demo required the coder to know where the x,y,width,height of each sprite on the spritesheet.
I am currently trying to make it so a grid of triangles will expand and move to the 'top' layer when you mouse over them, but then shrink back down to original size and move back to the original layer when you mouse out of them. However right now only the mouse over function is working correctly.
Here is the current code Im working with:
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
var secondLayer = new Kinetic.Layer();
var tri = new Kinetic.RegularPolygon({
x: stage.width()/2,
y: stage.height()/2,
sides: 3,
radius: 30,
fill: '#111111',
closed: true,
shadowColor: '#5febff',
shadowBlur: 5,
shadowOpacity: 0.18,
});
layer.add(tri);
stage.add(layer);
stage.add(secondLayer);
// bind stage handlers
layer.on('mouseover', function(evt) {
var shape = evt.targetNode;
shape.moveTo(secondLayer);
stage.draw()
var tween = new Kinetic.Tween({
node: shape,
duration: 0.05,
scaleX: 1.5,
scaleY: 1.5
});
tween.play()
});
secondLayer.on('mouseout', function(evt) {
var shape = evt.targetNode;
var tween = new Kinetic.Tween({
node: shape,
duration: 0.05,
scaleX: 1.5,
scaleY: 1.5
});
tween.reverse()
shape.moveTo(layer);
stage.draw();
});
And here is a jsfiddle: http://jsfiddle.net/y2C3Z/1/
You can use tween.reverse() only after tween.play(). So you can just change scale attributes to original values.
Don't move shape between layers while shape under a tween. You can move shape after tween is done.
http://jsfiddle.net/y2C3Z/3/
Below I have some code for an assignment I'm working on. Having been placed in a 2nd year course without taking foundations of JavaScript, I'm kind of in a rut.
I'm trying to place three images, and be able to call on them later with functions to change their opacity.
When I have the images placed, only one seems to want to appear at a time, and when I call to them, I'm told that they don't exist.
// Create the canvas based on the existing div for it in the HTML file
var stage = new Kinetic.Stage
({
container: 'canvasContainer',
width: 600,
height: 600
});
/* /////////////////////////////////////////////////////
C O D E F O R L O A D I N G U P I M A G E S
///////////////////////////////////////////////////// */
var characters = new Kinetic.Layer();
stage.add(characters);
window.onload = function()
{
var majoraCharacter = new Image();
majoraCharacter.src ="https://upload.wikimedia.org/wikipedia/commons/3/34/Red_star.svg"
majoraCharacter.onload = function()
{
character1= new Kinetic.Image({ x: 400, y: 300, width: 150, height: 150, offset: {x: 75, y: 75}, image: majoraCharacter});
characters.add(character1);
characters.draw();
}
}
window.onload = function()
{
var amaterasuCharacter = new Image();
amaterasuCharacter.src ="https://upload.wikimedia.org/wikipedia/commons/3/34/Red_star.svg"
amaterasuCharacter.onload = function()
{
character2= new Kinetic.Image({ x: 400, y: 200, width: 150, height: 150, offset: {x: 75, y: 75}, opacity:0.5, image: amaterasuCharacter});
characters.add(character2);
characters.draw();
}
}
window.onload = function()
{
var toothlessCharacter = new Image();
toothlessCharacter.src ="https://upload.wikimedia.org/wikipedia/commons/3/34/Red_star.svg"
toothlessCharacter.onload = function()
{
character3= new Kinetic.Image({ x: 400, y: 100, width: 150, height: 150, offset: {x: 75, y: 75}, image: toothlessCharacter});
characters.add(character3);
characters.draw();
}
}
/* /////////////////////////////////////////////////////
C A N V A S F U N C T I O N A L I T Y
///////////////////////////////////////////////////// */
// Create new layer for background images
// Create layer for character images
var character = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 100,
y: 100,
width: 150,
height: 150,
fill: 'grey',
strokeWidth: 4,
offset: {x: 75, y: 75},
});
// add the shape to the layer
character.add(rect);
// add the layer to the stage
stage.add(character);
Is there a way I can better add images to canvas?
And what is preventing them from co-existing, and being editable outside of their loading functions?
Any and all answers are greatly appreciated!
A Demo: http://jsfiddle.net/m1erickson/Bf88D/
Some KineticJS basics:
KineticJS starts with a stage.
The stage is a container for one or more layers which are added to the stage
Each layer is actually a canvas
Shapes (including images) are added to a layer.
Since you're new to javascript, here's an outline of how to structure your project
just use one window.onload and put all your javascript in that one window.onload
load all images in advance so they are available to draw on your canvas
When all the images are loaded, then create Kinetic.Image objects from them.
Here's an image loader that loads all your images in advance and then calls the start function when your images are fully loaded.
// image loader
var imageURLs=[]; // put the paths to your images here
var imagesOK=0;
var imgs=[];
imageURLs.push("");
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK>=imageURLs.length ) {
callback();
}
};
img.onerror=function(){alert("image load failed");}
img.crossOrigin="anonymous";
img.src = imageURLs[i];
}
}
function start(){
// the imgs[] array holds fully loaded images
// the imgs[] are in the same order as imageURLs[]
// use the images now!
}
After you have all your images loaded, you can use this reusable function to add Kinetic Images on the layer.
You send in one image that you've loaded in advance.
You also send in the x,y position where you want the image located.
You also send in the width,height that you want the image resized to.
This function adds one new image to the layer
function addKineticImage(image,x,y,w,h){
var image = new Kinetic.Image({
x:x,
y:y,
width:w,
height:h,
image:image,
draggable: true
});
layer.add(image);
layer.draw();
}