This the code that I use for the base64 conversation on the local browser
var render_width = chart.plotWidth;
var render_height = render_width * chart.chartHeight / chart.chartWidth;
// Get the chart's SVG code
var svg = chart.getSVG({
exporting: {
sourceWidth: chart.chartWidth,
sourceHeight: chart.chartHeight
}
});
// Create a canvas
var canvas = document.createElement('canvas');
canvas.id = "render";
canvas.height = render_height;
canvas.width = render_width;
//canvas.setAttribute('crossOrigin', 'anonymous');
//canvas.style = "display:hidden";
document.body.appendChild(canvas);
var dogImage = new Image;
//dogImage.setAttribute('crossOrigin', 'anonymous');
dogImage.onload = function() {
if (chart.plotWidth < chart.plotHeight) {
plot = chart.plotWidth;
} else {
plot = chart.plotHeight;
}
f = 0.65;
var imageHeight = plot * f;
var imageWidth = plot * f;
var textX = (chart.plotLeft + (chart.plotWidth * 0.5)) - (imageHeight / 2);
var textY = (chart.plotTop + (chart.plotHeight * 0.5)) - (imageWidth / 2);
canvas.getContext('2d').drawImage(this, textX, textY, imageWidth, imageHeight);
// Create an image and draw the SVG onto the canvas
var image = new Image;
//image.setAttribute('crossOrigin', 'anonymous');
image.onload = function() {
canvas.getContext('2d').drawImage(this, chart.plotLeft, 0, render_width, render_height);
var d = canvas.toDataURL("image/png");
//var w=window.open('about:blank','image from canvas');
var data = {
chart_image: d,
animal_id: animal_id
};
asyncRequest.postData(url, data, function(data) {
//console.log(data);
$("#loading-modal").addClass('display-none');
location.href = data.file_path;
});
//$('body').append("<img src='"+d+"' alt='from canvas'/>");
document.body.removeChild(canvas);
};
image.src = 'data:image/svg+xml;base64,' + window.btoa(svg);
};
dogImage.src = center_image;
This is working only if the allowHTMl is false inside the high charts options
exporting: {
// allowHTML: true,
buttons: {
exportButton: {
enabled: false
},
printButton: {
enabled: false
},
contextButton: {
enabled: false
}
}
},
is there a way that I can export the base64 with the allowHTML option. If the allowHTML is true and then it will send me back with a base64 that i cant use as an image src.This is for a Custom DOMPDF
Related
I am trying to crop an image with Javascript. I have croppr.js and it is sending the data and I was trying to crop the image so I can save it to a storage server with Base 64. I have read online about .drawimage(). I have tried:
function process(data) {
console.log("DATA:" + data)
var canvas = document.getElementById("canvas")
var context = canvas.getContext('2d');
var imageObj = new Image();
var zoom
imageObj.onload = function() {
context.width = data.width
context.height = data.height
// draw cropped image
var sourceX = data.x;
var sourceY = data.y;
var sourceWidth = data.width / 2;
var sourceHeight = data.height / 2;
var destWidth = sourceWidth;
var destHeight = sourceHeight;
var destX = 0;
var destY = 0;
context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight);
var dataurl = canvas.toDataURL('image/jpeg', 1.0)
console.log(dataurl)
};
imageObj.src = document.getElementsByTagName("img")[0].src;
console.log(imageObj.src)
}
data Contains X Y Height Width As an JSON array.
First I see is the:
context.width = data.width
context.height = data.height
Did you meant to do canvas instead?
Here is an example:
function process(data) {
var canvas = document.getElementById("canvas")
var context = canvas.getContext('2d');
var img = new Image();
img.onload = function() {
canvas.width = data.width
canvas.height = data.height
// draw cropped image
var w = data.width / 2;
var h = data.height / 2;
context.drawImage(img, data.x, data.y, w, h, 0, 0, w, h);
};
img.src = data.src;
}
process({x:0, y:0, width:600, height: 600, src: "http://i.stack.imgur.com/UFBxY.png"})
<canvas id="canvas"></canvas>
That is the only issue I could see on your code.
What is not clear is the data you use to call the process function
I found these two pieces of code and I'm quite new to Java. Essentially I'd like to be able to select the image from a file selector (like the first piece of code) instead of specifying the url of an image. Also, is there a way that I could output a list of all the coordinates to the console pr ideally create a txt file with the coords in?
I've left links to jsfiddle for both
thank you!!
http://jsfiddle.net/edprattt/m2a1j8yf/
https://jsfiddle.net/edprattt/8xqo71Lk/
##1
function showImage(src, target) {
var fr = new FileReader();
fr.onload = function(){
target.src = fr.result;
}
fr.readAsDataURL(src.files[0]);
}
function putImage() {
var src = document.getElementById("select_image");
var target = document.getElementById("target");
showImage(src, target);
}
##2
var canvas = document.getElementById('Canvas');
var context = canvas.getContext("2d");
var mapSprite = new Image();
mapSprite.src = "http://www.retrogameguide.com/images/screenshots/snes-legend-of-zelda-linkto-the-past-8.jpg";
var Marker = function () {
this.Sprite = new Image();
this.Sprite.src = "http://www.clker.com/cliparts/w/O/e/P/x/i/map-marker-hi.png"
this.Width = 12;
this.Height = 20;
this.XPos = 0;
this.YPos = 0;
}
var Markers = new Array();
var mouseClicked = function (mouse) {
// Get corrent mouse coords
var rect = canvas.getBoundingClientRect();
var mouseXPos = (mouse.x - rect.left);
var mouseYPos = (mouse.y - rect.top);
console.log("Marker added");
var marker = new Marker();
marker.XPos = mouseXPos - (marker.Width / 2);
marker.YPos = mouseYPos - marker.Height;
Markers.push(marker);
}
canvas.addEventListener("mousedown", mouseClicked, false);
var firstLoad = function () {
context.font = "15px Georgia";
context.textAlign = "center";
}
firstLoad();
var main = function () {
draw();
};
var draw = function () {
// Clear Canvas
context.fillStyle = "#000";
context.fillRect(0, 0, canvas.width, canvas.height);
// Draw map
// Sprite, X location, Y location, Image width, Image height
// You can leave the image height and width off, if you do it will draw the image at default size
context.drawImage(mapSprite, 0, 0, 700, 700);
// Draw markers
for (var i = 0; i < Markers.length; i++) {
var tempMarker = Markers[i];
// Draw marker
context.drawImage(tempMarker.Sprite, tempMarker.XPos, tempMarker.YPos, tempMarker.Width, tempMarker.Height);
// Calculate postion text
var markerText = "Postion (X:" + tempMarker.XPos + ", Y:" + tempMarker.YPos;
// Draw a simple box so you can see the position
var textMeasurements = context.measureText(markerText);
context.fillStyle = "#666";
context.globalAlpha = 0.7;
context.fillRect(tempMarker.XPos - (textMeasurements.width / 2), tempMarker.YPos - 15, textMeasurements.width, 20);
context.globalAlpha = 1;
// Draw position above
context.fillStyle = "#000";
context.fillText(markerText, tempMarker.XPos, tempMarker.YPos);
}
};
setInterval(main, (1000 / 60)); // Refresh 60 times a second
I have the following code that allows the user to upload an image which gets put into a canvas, but once it has been drawn I want users to be able to rotate the image with the click of a button, but I don't know how to re-access the image object to be able to rotate the canvas. The code below is what works:
onFilePicked (e) {
const files = e.target.files;
for (let file of files) {
if(file !== undefined) {
let image = {
thumbnail: '/img/spinner.gif'
};
this.images.push(image);
this.loadImage(file, image);
}
}
},
loadImage(file, image) {
const fr = new FileReader();
fr.readAsDataURL(file);
fr.addEventListener('load', () => {
var img = new Image();
img.src = fr.result;
img.onload = () => {
image.thumbnail = this.resizeImage(img, 400, 300);
image.large = this.resizeImage(img, 1280, 960);
}
})
},
resizeImage(origImg, maxWidth, maxHeight) {
let scale = 1;
if (origImg.width > maxWidth) {
scale = maxWidth / origImg.width;
}
if (origImg.height > maxHeight) {
let scale2 = maxHeight / origImg.height;
if (scale2 < scale) scale = scale2;
}
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = origImg.width * scale;
canvas.height= origImg.height * scale;
ctx.drawImage(origImg, 0, 0, canvas.width, canvas.height);
return canvas.toDataURL("image/jpeg");
},
And seen below is the function I built out to rotate the image- it works in that if I replace the code inside of the resizeImage function with the code below that the image is drawn in a way that is rotated correctly, but I don't know how to access the origImg object to be able to redraw the canvas in a separate function.
rotateImage(origImg, maxWidth, maxHeight){
let scale = 1;
if (origImg.width > maxWidth) {
scale = maxWidth / origImg.width;
}
if (origImg.height > maxHeight) {
let scale2 = maxHeight / origImg.height;
if (scale2 < scale) scale = scale2;
}
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = origImg.height * scale;
canvas.height= origImg.width * scale;
ctx.translate(canvas.width, 0);
ctx.rotate(90 * Math.PI / 180);
ctx.drawImage(origImg, 0, 0, canvas.height, canvas.width);
return canvas.toDataURL("image/jpeg");
},
Running this function as-is triggers the following console error:
Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'
How do I get/reuse the origImg object from the resizeImage function so I can use it in the rotateImage function?
you can try with this code:
var myCanvas = document.getElementById('my_canvas_id');
var ctx = myCanvas.getContext('2d');
var img = new Image;
img.onload = function(){
ctx.drawImage(origImg,0,0); // Or at whatever offset you like
};
And apply your code insede onload function of img and finally transform img source to date URL
Try this code, based on one file picker, two buttons. The first one resize image and the second one rotete the image
function resizeImg()
{
var oPicker = document.getElementById('avatar');
var oImage = document.getElementById('imgOut');
var file = oPicker.files[0];
const fr = new FileReader();
fr.readAsDataURL(file);
fr.addEventListener('load', () => {
var img = new Image();
img.src = fr.result;
img.onload = () => {
oImage.thumbnail = this.resizeImage(img, 400, 300);
oImage.src = this.resizeImage(img, 1280, 960);
}
})
}
function rotateImg()
{
var imgOut = document.getElementById('imgOut');
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
let scale = 1;
canvas.width = imgOut.height * scale;
canvas.height= imgOut.width * scale;
ctx.translate(canvas.width, 0);
ctx.rotate(90 * Math.PI / 180);
ctx.drawImage(imgOut, 0, 0, canvas.height, canvas.width);
imgOut.src = canvas.toDataURL("image/jpeg");
}
function resizeImage(origImg, maxWidth, maxHeight) {
let scale = 1;
if (origImg.width > maxWidth) {
scale = maxWidth / origImg.width;
}
if (origImg.height > maxHeight) {
let scale2 = maxHeight / origImg.height;
if (scale2 < scale) scale = scale2;
}
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
canvas.width = origImg.width * scale;
canvas.height= origImg.height * scale;
ctx.drawImage(origImg, 0, 0, canvas.width, canvas.height);
return canvas.toDataURL("image/jpeg");
}
<html>
<head>
<title>Test</title>
</head>
<body>
<h1>Image test</h1>
<img src="" id="imgOut" />
<label for="avatar">Choose a profile picture:</label>
<input type="file" id="avatar" name="avatar" accept="image/png, image/jpeg">
<input type="button" id="resImg" onclick="resizeImg()" value="Resize" />
<input type="button" id="rotImg" onclick="rotateImg()" value="Rotate" />
</body>
</html>
As you have a part in onFilePicked() where you store something about the images:
let image = {
thumbnail: '/img/spinner.gif'
};
this.images.push(image);
and later update the same objects in loadImage() (well, an event handler in it) as
image.thumbnail = this.resizeImage(img, 400, 300);
image.large = this.resizeImage(img, 1280, 960);
It could be simply extended to
image.original = img;
image.thumbnail = this.resizeImage(img, 400, 300);
image.large = this.resizeImage(img, 1280, 960);
Starting from this point, the objects in your images array would have an original field, storing the original, non-resized variant of the image.
Attempting to create a custom class that will display an image on the top left corner of a Fabric rectangle.
Extending the fabric class and calling ctx.drawImage isn't displaying anything.
var CustomRect = fabric.util.createClass(fabric.Rect, {
type: 'labeledRect',
initialize: function(options) {
options || (options = { });
const image = new Image();
image.src = signBtn;
this.callSuper('initialize', options);
this.set('label', options.label || '');
this.set('image', image);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
label: this.get('label')
});
},
_render: function(ctx) {
this.callSuper('_render', ctx);
ctx.font = '20px Helvetica';
ctx.fillStyle = '#333';
ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
ctx.drawImage(this.image, this.left+10, this.top-5, 15, 15);
}
});
fillText is working fine and displaying the label properly.
Tried a few different things thinking the image isn't loaded. It's imported as an SVG. I've gotten it to display in other ways but prefer to have a custom class handle this instead of event handlers.
You need to set image after load. You can use image.onload event callback, or use fabric.util.loadImage
DEMO
fabric.CustomRect = fabric.util.createClass(fabric.Rect, {
type: 'customRect',
initialize: function(options) {
options || (options = { });
var that = this;
this.imageLoaded = false;
fabric.util.loadImage(options.signBtn,function(img){
that.set('image', img);
that.imageLoaded = true;
that.dirty = true;
//if canvas is global
canvas.renderAll();
},{
crossOrigin : 'annonymous'
});
this.callSuper('initialize', options);
this.set('label', options.label || '');
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
label: this.label,
image : this.image
});
},
_render: function(ctx) {
this.callSuper('_render', ctx);
ctx.font = '20px Helvetica';
ctx.fillStyle = '#333';
ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
this.imageLoaded && ctx.drawImage(this.image, 10, -5, 15, 15);
}
});
fabric.CustomRect.fromObject = function(object, callback) {
return fabric.Object._fromObject('CustomRect', object, callback);
};
var url = 'https://upload.wikimedia.org/wikipedia/en/8/80/Wikipedia-logo-v2.svg';
var canvas = new fabric.Canvas('canvas');
var rect = new fabric.CustomRect({
signBtn: url,
left : 10,
top : 10,
width : 200,
height: 200,
fill: 'green',
label : 'test'
});
canvas.add(rect);
function loadfromjson() {
var json = canvas.toJSON();
canvas.clear();
setTimeout(function() {
canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
}, 1000)
}
canvas{
border:2px solid #000;
}
<script src='https://rawgit.com/kangax/fabric.js/master/dist/fabric.js'></script>
<canvas id="canvas" width="300" height="300"></canvas>
<button onclick="loadfromjson()">loadfromjson </button>
I believe there are some missing values like this.width and this.height?
In addition to that, you have to wait until the image is loaded to draw it. You can do something like this:
var CustomRect = fabric.util.createClass(fabric.Rect, {
type: 'labeledRect',
initialize: function(options) {
options || (options = { });
const image = new Image();
image.src = 'https://i.stack.imgur.com/CYp8Y.jpg';
this.callSuper('initialize', options);
image.onload = (function() {
this.width = image.width;
this.height = image.height;
this.image_loaded = true;
}).bind(this);
this.set('label', options.label || '');
this.set('image', image);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
label: this.get('label')
});
},
_render: function(ctx) {
if (this.image_loaded) {
this.callSuper('_render', ctx);
console.log(-this.width / 2, -this.height / 2);
ctx.font = '20px Helvetica';
ctx.fillStyle = '#333';
ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
}
}
});
Note these two changes:
image.onload = (function() {
this.width = image.width;
this.height = image.height;
this.image_loaded = true;
}).bind(this);
I set the image_loaded to true inside the initialize method once the image is loaded. Then in the _render method I check if the image is loaded, and then draw it.
if(this.loaded){
//............
ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
}
Here's a fiddle: https://jsfiddle.net/nimeshka/enL61g0w/55/
You might need to click on the canvas to trigger the render event. Otherwise you won't see the rectangle in the output box. (I haven't added it)
Hope it helps :)
I'm developing a game using HTML5 canvas element and native javascript. I have different sprites for game objects. Is it possible to rotate sprites using native javascript?
For example, I have a sprite image like this:
I use Image for this sprite:
var image = new Image(...);
image.src = "...";
After loading I want to rotate this image and save different projections in local variables:
var sprite_left = rotate(image, 0),
sprite_top = rotate(image, 90),
sprite_right = rotate(image, 180),
sprite_right = rotate(image, 270);
The rotate function should look like this:
function rotate(sourceImage, angle){
...
}
Could anybody help me to write the rotate function?
EDIT:
I have decided to share my code, which I used to test my sprites:
var wait = function (image, completed, count) {
if (count == null) count = 0;
if (!image.complete && count < 1000) {
count++;
window.setTimeout(function () {
wait(image, completed, count);
console.log('waiting...');
}, 10);
}
else {
completed();
}
},
rotateW = function (image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var p = document.createElement("p");
p.innerText = "W: ";
p.appendChild(canvas);
document.body.appendChild(p);
var context = canvas.getContext("2d");
context.translate(canvas.width / 2, canvas.height / 2);
context.rotate(Math.PI);
context.translate(-canvas.width / 2, -canvas.height / 2);
context.drawImage(image, 0, 0);
var newImage = new Image();
newImage.src = canvas.toDataURL("image/png");
return newImage;
},
rotateE = function (image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var p = document.createElement("p");
p.innerText = "E: ";
p.appendChild(canvas);
document.body.appendChild(p);
var context = canvas.getContext("2d");
context.drawImage(image, 0, 0);
var newImage = new Image();
newImage.src = canvas.toDataURL("image/png");
return newImage;
},
rotateS = function (image, frameCount) {
var canvas = document.createElement("canvas");
canvas.width = image.height * frameCount;
canvas.height = image.width / frameCount;
var p = document.createElement("p");
p.innerText = "S: ";
p.appendChild(canvas);
document.body.appendChild(p);
var context = canvas.getContext("2d");
context.translate(image.height / 2, image.width / (2 * frameCount));
context.rotate(Math.PI / 2);
var i = frameCount;
while (i--> 0) {
context.drawImage(image, - image.width / 2 , - ( 0.5 + i ) * image.height);
}
var newImage = new Image();
newImage.src = canvas.toDataURL("image/png");
return newImage;
},
rotateN = function (image, frameCount) {
var canvas = document.createElement("canvas");
canvas.width = image.height * frameCount;
canvas.height = image.width / frameCount;
var p = document.createElement("p");
p.innerText = "N: ";
p.appendChild(canvas);
document.body.appendChild(p);
var context = canvas.getContext("2d");
context.translate(image.height / 2, image.width / (2 * frameCount));
context.rotate( 3 * Math.PI / 2);
var i = frameCount;
while (i-- > 0) {
context.drawImage(image, -image.width / 2, (frameCount - i - 1.5) * image.height);
}
var newImage = new Image();
newImage.src = canvas.toDataURL("image/png");
return newImage;
};
/*
N
|
W----O----E
|
S
*/
getSprites = function (image, frameCount) {
var sprite = {
N: rotateN(image, frameCount),
S: rotateS(image, frameCount),
W: rotateW(image, frameCount),
E: rotateE(image, frameCount)
};
return [
sprite.W, // left
sprite.N, // up
sprite.E, // right
sprite.S] // down
};
$.sprite = {
register: function (options) {
var image = new Image();
image.src = options.src;
wait(image, function () {
var sprites = getSprites(image, options.frameCount);
});
}
};
The final result is:
the following function will create a new Canvas out
of img (which might be an image or a canvas).
Give it an angle in radian, or 'N', 'S', 'W' for
the corresponding rotation.
function createRotatedImage(img, angle) {
angle = (angle == 'N') ? -Math.PI/2 :
(angle == 'S') ? Math.PI/2 :
(angle == 'W') ? Math.PI :
angle ;
var newCanvas = document.createElement('canvas');
newCanvas.width = img.width ;
newCanvas.height = img.height ;
var newCtx = newCanvas.getContext('2d') ;
newCtx.save () ;
newCtx.translate ( img.width / 2, img.height / 2) ;
newCtx.rotate (angle);
newCtx.drawImage ( img, - img.width / 2, - img.height / 2) ;
newCtx.restore () ;
}
Use a <canvas> to pre-render the different rotations
Store these in memory using via toBlob, optionally converting these blobs to URLs with window.URL.createObjectURL
Swap URLs as desired.
See this MDN page for canvas options
Absolutely! It's not as simple as rotating the image, though. You need to rotate the context from the canvas, and draw that image on the rotated context, and then restore it.
context.save();
context.rotate(angle);
//DRAW IT!
context.restore();
How about having a function like :
Image.prototype.rotate = function(angle) {
var c = document.createElement("canvas");
c.width = this.width;
c.height = this.height;
var ctx = c.getContext("2d");
ctx.rotate(angle);
var imgData = ctx.createImageData(this.width, this.height);
ctx.putImageData(imgData);
return new Image(imgData);
}
var img1 = new Image();
var img2 = img1.rotate(90);
Ofcourse it's just a quick sample to give you an idea.