Change Image on Hover in KineticJS - hover

I'm looking to change an image on hover in KineticJS. What happens now is that the image just appends to the layer, doesn't actually swap the image. Without removing the layer, I want to swap the image with another. Here's my code.
imgObj.onload = function () {
var image = new Kinetic.Image({
x: 10,
y: 10,
image: imgObj,
width: 28,
height: 28,
id: 'myImage'
});
image.on("mouseenter", function (e) {
document.body.style.cursor = 'pointer';
imgObj.src = 'myHoverImage.png';
layer.draw();
});
image.on("mouseleave", function () {
document.body.style.cursor = 'default';
imgObj.src = 'myImage.png';
});

Use .setImage on the Kinetic.Image to swap to a different image:
Preload both images into image objects with var hoverImage=new Image() ... and var blurImage=new Image() ....
Important: Be sure both images have fully loaded using the .onload method of the image objects.
In the event handlers, swap images with image.setImage(hoverImage) or image.setImage(blurImage).
Display the swapped image with layer.draw().

Related

Dashed Line SVG Animation

I'm newer to working with SVG animations so I apologize in advanced if there is a straightforward answer to this. With a combination of utilizing Scrollmajic.js and GASP I was able to get the SVG to animate when the user scrolls to a specific position. The issue i'm running into is that the animation converts it from a dashed line to a solid stroke. I've done some research and found that using a mask would be the best way to accomplish this though I'm a bit lost on how to approach this method.
https://codepen.io/ncanarelli/pen/wvaeLNa
js:
$(document).ready(function() {
function pathPrepare ($el) {
var lineLength = $el[0].getTotalLength();
$el.css("stroke-dasharray", lineLength);
$el.css("stroke-dashoffset", lineLength);
}
// init controller
var controller = new ScrollMagic.Controller();
// loop through all elements
$(".svg-animation").each(function() {
var $thePath = $(this).find("path#thePath");
// prepare SVG
pathPrepare($thePath);
// build tween
var tween = new TimelineMax()
.add(TweenMax.to($thePath, 1, {
strokeDashoffset: 0,
ease:Linear.easeNone
}))
// build scene
var scene = new ScrollMagic.Scene({
triggerElement: $(this)[0],
duration: 200,
tweenChanges: true,
reverse: true
})
.setTween(tween)
.addTo(controller)
.addIndicators();
});
});
UPDATE: Updated .js to reflect an .each loop + other modifications. Still having issues with implementing a mask.

Adding static image to Lightswitch HTML 2013 Browse Screen

In my case, I have color coded some tiles in the HTML client and I want to add a simple color code key. I have the PNG file I want to use.
I do not require the ability to upload or change the image.
This link seems to achieve what I am looking for, but I am not sure where to implement. Does all of this code go into the PostRender of the Image Control I created?
Add image to lightswitch using local property and file location
Here is what the PostRender of the simple Image data item I created as an Image Local Property, and then dragged into the Solution Designer. It was basically copied from the link above, but I did change the name of the image file to match mine, and I have already added the item to the Content\Images folder structure and it shows in the file view:
myapp.BrowseOrderLines.ColorKey_postRender = function (element, contentItem) {
// Write code here.
function GetImageProperty(operation) {
var image = new Image();
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
// XMLHttpRequest used to allow external cross-domain resources to be processed using the canvas.
// unlike crossOrigin = "Anonymous", XMLHttpRequest works in IE10 (important for LightSwitch)
// still requires the appropriate server-side ACAO header (see https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image)
var xhr = new XMLHttpRequest();
xhr.onload = function () {
var url = URL.createObjectURL(this.response);
image.onload = function () {
URL.revokeObjectURL(url);
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0);
var dataURL = canvas.toDataURL("image/png");
operation.complete(dataURL.substring(dataURL.indexOf(",") + 1));
};
image.src = url;
};
xhr.open('GET', this.imageSource, true);
xhr.responseType = 'blob';
xhr.send();
};
myapp.BrowseOrderLines.ColorKey_postRender = function (element, contentItem) {
// Write code here.
msls.promiseOperation
(
$.proxy(
GetImageProperty,
{ imageSource: "content/images/Key.png" }
)
).then(
function (result) {
contentItem.screen.ImageProperty = result;
}
);
};
}
Currently, the Image control does show on the screen in the browser, and is the custom size I choose, but it is just a light blue area that does not display my image file.
I am not sure if I have embedded the image? I am not sure if that is a missing step?
Thank you!!
The easiest method of testing this approach would be to change your postRender to the following (which embeds the helper function within the postRender function):
myapp.BrowseOrderLines.ColorKey_postRender = function (element, contentItem) {
function GetImageProperty(imageSource) {
return msls.promiseOperation(
function (operation) {
var image = new Image();
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
// XMLHttpRequest used to allow external cross-domain resources to be processed using the canvas.
// unlike crossOrigin = "Anonymous", XMLHttpRequest works in IE10 (important for LightSwitch)
// still requires the appropriate server-side ACAO header (see https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image)
var xhr = new XMLHttpRequest();
xhr.onload = function () {
var url = URL.createObjectURL(this.response);
image.onload = function () {
URL.revokeObjectURL(url);
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0);
var dataURL = canvas.toDataURL("image/png");
operation.complete(dataURL.substring(dataURL.indexOf(",") + 1));
};
image.onerror = function () {
operation.error("Image load error");
};
image.src = url;
};
xhr.open('GET', imageSource, true);
xhr.responseType = 'blob';
xhr.send();
}
);
};
GetImageProperty("content/images/Key.png").then(function onComplete(result) {
contentItem.screen.ImageProperty = result;
}, function onError(error) {
msls.showMessageBox(error);
});
};
This assumes that you named the local property ImageProperty as per my original post and the Image control on your screen is named ColorKey.
In the above example, I've also taken the opportunity to slightly simplify and improve the code from my original post. It also includes a simple error handler which may flag up if there is a problem with loading the image.
If this still doesn't work, you could test the process by changing the image source file-name to content/images/user-splash-screen.png (this png file should have been added as a matter of course when you created your LightSwitch HTML project).
As the GetImageProperty function is a helper routine, rather than embedding it within the postRender you'd normally place it within a JavaScript helper module. This will allow it to be easily reused without repeating the function's code. If you don't already have such a library and you're interested in implementing one, the following post covers some of details involved in doing this:
Lightswitch HTML global JS file to pass variable

How to hide the overflow of photos in canvas?

I am trying making a photo frame pattern on canvas. In which I want to put two, three or maybe more photos under an overlay frame. Where few parts of the overlay frame are transparent.
If I upload photo1 into first section of frame its visible into second section also and uploading photo2 into section two is also visible into first section. Depending on which photo is uploaded first or edited at last is overlapping the other photo.
I want to know how to hide the overflow of photo so it should not be visible into other sections. How can I achieve this?
I have done this so far:
canvas.on({
'object:moving': onChange,
'object:scaling': onChange,
'object:rotating': onChange,
});
function onChange(options) {
options.target.setCoords();
canvas.forEachObject(function (obj) {
if (obj === options.target)
return;
if (obj.id != 'cover1' && obj.id != 'cover2')
return;
if (options.target.intersectsWithObject(obj)) {
// Hide this portion
canvas.renderAll();
}
});
}
Kindly provide me the best solution
You need to apply a clipTo() method onto the image.
var canvas;
$(function(){
canvas = window._canvas = new fabric.Canvas('canvas');
var radius = 200;
fabric.Image.fromURL('http://fabricjs.com/assets/pug_small.jpg', function(img) {
img.scale(0.5).set({
left: 250,
top: 250,
angle: -15,
clipTo: function (ctx) {
ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
}
});
canvas.add(img).setActiveObject(img);
});
});
This fiddle show the technique
Fiddle

KineticJS - How to Change Image src on Button Click

I'm trying to change the src of an image in my kineticjs stage on a button click.
I have a draggable image (in this case darth-vader) and a static image on top (in this case monkey). On the click of a button i want to be able to replace the draggable image with a new one (yoda)
JSFiddle can be seen here:
http://jsfiddle.net/SkVJu/33/
I thought the following:
btn.addEventListener("click", function (event) {
mainImage.src = path+'yoda.jpg';
layer.removeChildren();
draw(mainImage,true);
draw(foregroundImage,true);
});
would accomplish it: first by updating the src, then removing all objects and redrawing both again in the correct order.
For some reason though i get 2 yoda images placed on the stage - 1 correctly behind but another above everything else...
Instead of removing all the children and adding them back, you can swap image sources easily by using the KineticJS setImage function and passing in a Javascript Image Object: http://kineticjs.com/docs/Kinetic.Image.html#setImage
I updated your draw function so that it takes an id and name so that we can select the Kinetic Image object later:
// Draw function
function draw(image,drag,id,name){
if (typeof id == 'undefined') id = '';
if (typeof name == 'undefined') name = '';
var img = new Kinetic.Image({
image: image,
draggable: drag,
id: id,
name: name
});
layer.add(img);
layer.draw();
return img;
}
and then here is your update click function:
// Change draggable Image
btn.addEventListener("click", function (event) {
layer.get('#mainImageId')[0].setImage(mainImage2); //get the object with id "mainImageId"
layer.draw();
});
jsfiddle
Also, I moved your foregroundImage load function inside the mainImage onload function so that we make sure the Monkey is added to the stage after the mainImage:
// Define draggable image
var mainImage = new Image();
mainImage.onload = function () {
draw(mainImage,true, 'mainImageId');
// Define foreground image
var foregroundImage = new Image();
foregroundImage.onload = function () {
draw(foregroundImage,false);
};
foregroundImage.src = path+'monkey.png';
};
mainImage.src = path+'darth-vader.jpg';
Wouldn't it be easier to load both images right away, create new Kinetic.Group of them, set one visible and other hidden, than just create function that will hide first and show second on click? Just asking cause i have similar issue to deal with, just that in my case exchange should be done among 5 different icons based on settings parameter that user can change...

Kinetic JS, touch/hover this, affect all other objects

So, I'll try to explain this as best as I can: I have a canvas with a bunch of objects to touch have a highlighted state (swapping a background image as you can see here). I'm only showing 2 examples here for the objects 'applications' and 'enterprises', but there are many of these objects. My goal is to allow one object to have its hover image, while the rest do not. Once I click on another object, I want that object's hover image to activate, and hover images for all other objects removed (essentially getting rid of the 'touched mouseout' function.
I'd like to say something like:
'If touchstart/mouseover this object, use its hover image, and disable all hover images on all other objects.
applications.on('touchstart mouseover', function() {
writeMessage(messageLayer, 'touchstart applications circle');
this.setFill({ image: images.applicationshover});
layer.draw();
});
applications.on('touchend mouseout', function() {
writeMessage(messageLayer, 'Mouseup applications circle');
this.setFill({ image: images.applicationsimage});
layer.draw();
});
enterprises.on('touchstart mouseover', function() {
writeMessage(messageLayer, 'touchstart enterprises circle');
this.setFill({ image: images.enterpriseshover});
layer.draw();
});
enterprises.on('touchend mouseout', function() {
writeMessage(messageLayer, 'Mouseup enterprises circle');
this.setFill({ image: images.enterprisesimage});
layer.draw();
});
I hate answering questions to something I know little of without an example to tweak, but here goes....
Instead of what ever your doing, why not try this....
When you create your shapes/images add an attribute to them that is the image to use for the hover and not hover state.
Kinda like this....
var thing = new Kinetic.Image({
x: 0,
y: 0,
image: imageObj,
hoverImage: hoverImageObj,
notHoverImage: imageObj,
name: 'image'
});
Then you can have one routine for all images...
var hover = function() {
writeMessage(messageLayer, 'touchstart enterprises circle');
this.setFill({
image: this.attrs.hoverImage
});
layer.draw();
}
var notHover = function() {
writeMessage(messageLayer, 'Mouseup enterprises circle');
this.setFill({
image: this.attrs.notHoverImage
});
layer.draw();
}
icons.on('touchstart mouseover', hover);
icons.on('touchend mouseout', notHover);
There could be better ways to do this, Ive really got to go read the docs ;)