Alternate/Fallback Image while using Snap SVG - javascript

I have just downloaded Snap SVG and I'm trying to figure out how to display an image with a fall back arrangement. Here is the code:
var s = Snap("#MyPopup");
var g = s.g();
var image = g.image("http://myimages.com/xyz.png", 250, 10, 40,40 );
This displays the image perfectly. However, if the image is missing then you get that broken image-not-fond icon. Instead of that I want to display an alternate image, say http://myimages.com/abc.png , if the primary image is not found (similar to onerror used with <img>). Can someone please guide me how to do that.

Taking cue from #AustinC I have slightly modified the solution given at Check if image exists on server using JavaScript? that he suggested.
Basically the suggested function was returning 403 (instead of 404) as my images were hosted at amazon cloud, hence I opted to check return code 200 (OK). Here is the final solution.
var s = Snap("#MyPopup");
var image = null;
var mImagePath = "https://myimages.com/xyz.png";
if ( imageExists (mImagePath) == true ) {
image = s.image(mImagePath, 250, 10, 40,40 );
} else {
image = s.image("https://myimages.com/ImageNotFound.png", 250, 10, 40,40 );
}
function imageExists(image_url){
var http = new XMLHttpRequest();
http.open('HEAD', image_url, false);
http.send();
return http.status == 200;
}

Related

How to solve " The canvas has been tainted by cross-origin data." when I try to use getImageData

I have tried to implement a invert color function to my function, but I don't how to solve this thing with Cross Origin.
I have tried to use the "Anonymous", but that does not work too. So the question is pretty simple. How to use this getImageData correctly?
var canvasOriginal = document.getElementById("imagemOriginal");
var ctxOriginal = canvasOriginal.getContext("2d");
var imgOriginal = new Image();
var imgOut = new Image();
imgOriginal.src = 'images-png/img1.png';
imgOriginal.onload = function (){
ctxOriginal.drawImage(imgOriginal,0,0,512,512);
imgOut = ctxOriginal.getImageData(0,0,512,512);
for (let i = 0; i < imgOut.data.length; i += 4) {
imgOut.data[i] = 255 - imgOut.data[i];
imgOut.data[i+1] = 255 - imgOut.data[i+1];
imgOut.data[i+2] = 255- imgOut.data[i+2] ;
}
ctxOriginal.putImageData(imgOut, 512, 0);
};
Yes, I created a localhost and it has worked, but I had to add an extension on Google Chrome called "Allow-Control-Allow-Origin" to work. Thanks!
I think that the error is because your browser knows itself as localhost (or server you are on) and the canvas thinks your image is not coming from localhost or that server. If you're uploading locally your image should be something like
<img src="blob:http://your-server-address-or-localhost/image-id-returned-from-upload">
or if the image already exists, it would be something similar:
<img src="http://your-server-address-or-localhost/images-png/img1.png">
I imagine what you have is something like this:
<img src="/images-png/img1.png">
and that trips up the canvas
Your imgOriginal.src should be:
imgOriginal.src = 'http://localhost:3000/images-png/img1.png';
Hope this helps.

Fabric.js: Error when loading image from parameterized URL

I'm trying to load an image from an external URL. The image is retrieved dynamically from a database and is therefore not a direct path. An example of such URL is: http://192.192.168.12:8080/api/imageServer?file=imageName.jpeg. The response in an actual jpeg image; when I add the URL to an image tag or directly in the browser the image is shown. When I try to load the image into Fabric.js I only get the console message "Error loading " without any other message.
This is part of our code:
var updateCanvas = function () {
self.canvas.clear();
if (self.selectedImage() && self.canvas) {
try {
fabric.Image.fromURL(self.selectedImage().imageUrl, function (oImg) {
if (oImg._element == null) {
stickyToast(translations().Error, translations().img_bind_error, "error");
return;
}
self.canvas.clear();
var canvasHeight = 500;
var ratio = canvasHeight / oImg.height;
var canvasWidth = oImg.width * ratio;
//Define all filters that will be used on image
oImg.filters[0] = new fabric.Image.filters.Brightness({
brightness: 0
});
...
I've tried upgrading to the latest version of fabric.js but to no avail. Is there another method I need to use download the image?

Drawing on canvas after megapix rendering is reversed

I have a page which allows you to browse in an image, then draw on it and save both the original and the annotated version. I am leveraging megapix-image.js and exif.js to help in rendering images from multiple mobile devices properly. It works great, except in certain orientations. For example, a vertical photo taken on an iPhone4s is considered orientation 6 by exif and gets flipped accordingly by megapix-image so it's rendered nicely on the canvas. For some reason, when I draw on it afterward, it seems like the drawing is reversed. Mouse and touch both behave the same way. The coordinates look right to me (meaning they match a working horizontal pic and a non-working vertical pic), as does the canvas height and width when megapix-image.js flips it. This leads me to believe it has something to do with the context, but honestly, I am not really sure. I have a JS fiddle of the part of my work that shows the behavior. Just browse in a vertically taken pic from a mobile device or take a pic in vertical format on a mobile device and use it. I think all will show this same behavior.
The final rendering is done like this:
function RenderImage(file2) {
if (typeof file2[0].files[0] != 'undefined') {
EXIF.getData(file2[0].files[0], function () {
orientation = EXIF.getTag(this, "Orientation");
var file = file2[0].files[0];
var mpImg = new MegaPixImage(file);
var resCanvas1 = document.getElementById('annoCanvas');
mpImg.render(resCanvas1, {
maxWidth: 700,
maxHeight: 700,
orientation: orientation
});
});
}
}
But the full jsfiddle is here:
http://jsfiddle.net/awebster28/Tq3qU/6/
Does anyone have any clues for me?
If you look at the lib you are using there is a transformCoordinate function that is used to set the right transform before drawing.
And they don't save/restore the canvas (boooo!!!) so it remains with this transform after-wise.
Solution for you is to do what the lib should do : save the context before the render and restore it after :
function RenderImage(file2) {
// ... same code ...
var mpImg = new MegaPixImage(file);
var eData = EXIF.pretty(this);
// Render resized image into canvas element.
var resCanvas1 = document.getElementById('annoCanvas');
var ctx = resCanvas1.getContext('2d');
ctx.save();
//setting the orientation flips it
mpImg.render(resCanvas1, {
maxWidth: 700,
maxHeight: 700,
orientation: orientation
});
ctx.restore();
//...
}
I ended up fixing this by adding another canvas to my html (named "annoCanvas2"). Then, I updated megapix-image.js to include this function, which draws the contents of the new canvas to a fresh one:
function drawTwin(sourceCanvas)
{
var id = sourceCanvas.id + "2";
var destCanvas = document.getElementById(id);
if (destCanvas !== null) {
var twinCtx = destCanvas.getContext("2d");
destCanvas.width = sourceCanvas.width;
destCanvas.height = sourceCanvas.height;
twinCtx.drawImage(sourceCanvas, 0, 0, sourceCanvas.width, sourceCanvas.height);
}
}
Then, just after the first is rotated and flipped and rendered, I rendered the resulting canvas to my "twin". Then I had a nice canvas, with my updated image that I could then draw on and also save!
var tagName = target.tagName.toLowerCase();
if (tagName === 'img') {
target.src = renderImageToDataURL(this.srcImage, opt, doSquash);
} else if (tagName === 'canvas') {
renderImageToCanvas(this.srcImage, target, opt, doSquash);
//------I added this-----------
drawTwin(target);
}
I was glad to have it fixed so I met my deadline, but I am still not sure why I had to do this. If anyone out there can explain it, I'd love to know why.

Images not preloaded properly

I am having a jQuery script that loads 15 images and their hover versions (the hover versions are used when... hovering, not when the page loads). In both Chrome and Firefox in the Network tab, i see this :
images/img1.png
images_hover/img1.png
This must mean the hover images are preloaded correctly, but... when i actually hover and those images are used, they are being loaded again. Here is the preload code :
var prel = new Image();
prel.src = "http://hdodov.byethost15.com/color-game/graphics/parts_hover/" + id + ".png";
I tried using the whole path - http://hdodov.byethost15.com/color-game/graphics/parts_hover/ and the short path too (where the root and the script is) - graphics/parts_hover/. It made no difference.
Could this be caused because my images have the same name? They are in different directories though.
For the next question, you really should paste more code, which makes it easier to help you. I checked your URL you provided, but for other people that might have the same problem, it will be hard to understand what went wrong...
OK, as I said, you are always requesting he images again on hover state...
This worked for me:
var context = new Array(15),
canvas = new Array(15),
canvasNum = -1,
hElem,
hElemPrev,
mousePos = {x:-1, y:-1},
images = [], //<-- Store preloaded images here
imagesHover = []; //<-- Store preloaded images here
... then save them on building like this:
function drawMenuItems(id, width, height){
var canNumHolder, createCanvas;
$('#canvas_holder').append($('<canvas></canvas>')
.attr({
width:width,
height:height,
id:id
})
);
canvasNum++;
canvas[canvasNum] = document.getElementById(id);
context[canvasNum] = canvas[canvasNum].getContext('2d');
canNumHolder = canvasNum;
images[id].crossOrigin = 'Anonymous';
images[id].onload = function(){
context[canNumHolder].drawImage(images[id],0,0);
};
images[id].src = 'graphics/parts/' + id + '.png';
//Hover states
imagesHover[id] = new Image();
imagesHover[id].src = "graphics/parts_hover/" + id + ".png";
}
... give just the id...
function hoverStateChange() {
//....rest of the code
if(hElem >= 0){
drawImageOnCanvas(
canvas[hElem],
context[hElem],
"hover", //pass somethink to checke what you want to do
$(canvas[hElem]).attr('id')
);
//....rest of the code
//change to normal texture
if(hElemPrev >= 0){
drawImageOnCanvas(
canvas[hElemPrev],
context[hElemPrev],
"", //pass empty for other state
$(canvas[hElemPrev]).attr('id')
);
$(canvas[hElemPrev]).removeClass('active');
$('#text_holder').removeClass('a' + hElemPrev);
}
.. and finally
function drawImageOnCanvas(canv, contxt, state, src){
contxt.clearRect(0,0,400,400);
if(state == "hover"){
contxt.drawImage(imagesHover[src],0,0);
}else {
contxt.drawImage(images[src],0,0);
}
}
Like this, you chache you images and not calling them again and again...
I hope it helps.
Yuo can preload images with css like this:-
#preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }

cc.sprite.create not working? cocos2d-html

I am new to Cocos2d-html5 v2.2.1 and I am trying to add a sprite (simple image) to the canvas. The code does add an image with the correct width and height but it is just black.
I cant seem to find any errors so I am kinda stuck.
Any help would be great. My code is below:
In main.js i load the resources:
applicationDidFinishLaunching:function () {
if(cc.RenderDoesnotSupport()){
//show Information to user
alert("Browser doesn't support WebGL");
return false;
}
// initialize director
var director = cc.Director.getInstance();
//cc.EGLView.getInstance()._adjustSizeToBrowser();
//cc.EGLView.getInstance()._resizeWithBrowserSize(true);
//cc.EGLView.getInstance().setDesignResolutionSize(600, 400, cc.RESOLUTION_POLICY.SHOW_ALL);
// set FPS. the default value is 1.0/60 if you don't call this
director.setAnimationInterval(1.0 / this.config['frameRate']);
//load resources
cc.LoaderScene.preload(g_resources, function () {
director.replaceScene(new this.startScene());
}, this);
return true;
}
g_resources is defined in resource.js:
var s_jet = "images/jet.png";
var s_character = "images/p1_front.png";
var g_resources = [
//image
{src:s_jet},
{src:s_character}];
spriteScene.js:
init:function () {
var selfPointer = this;
this._super();
var size = cc.Director.getInstance().getWinSize();
var lazyLayer = cc.LayerColor.create(new cc.Color4B(45, 50, 128, 255), 600, 600);
//var lazyLayer = cc.Layer.create();
lazyLayer.setAnchorPoint(new cc.Point(0.5,0.5));
var characterSprite = cc.Sprite.create("./images/p1_front.png");
lazyLayer.addChild(characterSprite, 0);
this.addChild(lazyLayer);
var rotateToA = cc.RotateTo.create(2, 0);
var scaleToA = cc.ScaleTo.create(2, 1, 1);
characterSprite.setPosition(new cc.Point(size.width/2,size.height/2));
I just dont understand why the sprite is just being drawn as a black box.
Edit: When I uncomment the line below from main.js; at first the image is still black but when I resize the browser, the image appears:-
cc.EGLView.getInstance().setDesignResolutionSize(600, 400, cc.RESOLUTION_POLICY.SHOW_ALL);
I dont know what this is implying.
Ok guys! I figured it out and I am pissed. Changed this line:
this.characterSprite.setPosition(new cc.Point(size.width/2,size.height/2));
to:
this.characterSprite.setPosition(cc.p(size.width/2, size.height/2));
Documentation/tutorials for cocos2d-html5 are outdated and this is getting frustrating.

Categories