Crop image after rotation; using Javascript, HTML5 Canvas, and Hammer mobile - javascript

I am working on a photo editing feature in a mobile angular app and would love help with the crop function in this JSBin http://jsbin.com/kofetuxage/1/edit. Basically, the image is not translating correctly to it's accurate position on the new HTML5 canvas element.
The JSBin is only somewhat functional because I cannot include a link to angular-gestures, so here's the HTML & relevant Javascript. Any help would be most appreciated!
------------ HTML --------------
<html>
<head>
<style>
canvas {
border:1px solid red;
}
.polaroid-crop {
width: 504px;
height: 385px;
border: 1px solid $orange;
overflow: hidden;
}
</style>
</head>
<body>
<p>Canvas (Left) and New clipped PNG (Right)</p>
<canvas id="canvas" width="504" height="385"></canvas>
<p>Original Image</p>
<p><div class="polaroid-crop">
<img src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/faces.png"
width="400"
height="234"
ng-style="calcStyle(rotation, scaleFactor, changeY, changeX)"
hm-tap="handleGesture($event)"
hm-double-tap="handleGesture($event)"
hm-hold="handleGesture($event)"
hm-swipe="handleGesture($event)"
hm-drag="drag($event)"
hm-rotate="rotate($event)"
hm-pinch="pinch($event)">
</div></p>
<button ng-click="clipIt()">Click me to clip dragged ones!</button>
</body>
</html>
------------ JAVASCRIPT --------------
'use strict';
angular.module('app.activity', [])
.controller('ActivityCtrl', ['$scope', 'UtilsService', function ($scope, UtilsService) {
$scope.rotation = 0;
$scope.scaleFactor = 1;
$scope.changeX = 0;
$scope.changeY = 0;
$scope.negativeChangeX = 0;
$scope.negativeChangeY = 0;
$scope.absX = 0;
$scope.absY = 0;
$scope.rotationRadian = 0;
$scope.canvasWidth = 504;
$scope.canvasHeight = 385;
$scope.imgWidth = 400;
$scope.imgHeight = 234;
$scope.rotate = function(event) {
console.log('rotation data', event);
$scope.type = event.type;
$scope.rotation = event.gesture.rotation % 360;
$scope.rotationAngle = event.gesture.rotation; // this was not working when it was getting angle instead of rotation
$scope.changeX = event.gesture.deltaX;
$scope.changeY = event.gesture.deltaY;
$scope.negativeChangeX = -(event.gesture.deltaX);
$scope.negativeChangeY = -(event.gesture.deltaX);
$scope.absX=Math.abs(event.gesture.deltaX);
$scope.absY=Math.abs(event.gesture.deltaY);
event.gesture.preventDefault();
// event.gesture.stopPropagation();
};
$scope.pinch = function(event) {
if (event.gesture.scale != 1) {
console.log('what does pinching return');
$scope.type = event.type;
$scope.scaleFactor = event.gesture.scale;
$scope.changeX = event.gesture.deltaX;
$scope.changeY = event.gesture.deltaY;
$scope.negativeChangeX = -(event.gesture.deltaX);
$scope.negativeChangeY = -(event.gesture.deltaX);
$scope.absX=Math.abs(event.gesture.deltaX);
$scope.absY=Math.abs(event.gesture.deltaY);
// event.gesture.preventDefault();
event.preventDefault();
// event.stopPropagation();
}
};
$scope.drag = function(event) {
$scope.type = event.type;
console.log('deltaX', event.gesture.deltaX, 'and deltaY', event.gesture.deltaY);
$scope.changeX = event.gesture.deltaX;
$scope.changeY = event.gesture.deltaY;
$scope.negativeChangeX = -(event.gesture.deltaX);
$scope.negativeChangeY = -(event.gesture.deltaY);
$scope.absX=Math.abs(event.gesture.deltaX);
$scope.absY=Math.abs(event.gesture.deltaY);
};
$scope.type = '--';
$scope.handleGesture = function($event) {
console.log('and the event type is', $event.type)
$scope.type = $event.type;
};
// from codedrops html crop example at http://tympanus.net/codrops/2014/10/30/resizing-cropping-images-canvas/
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
$scope.calcStyle = function (rotation, scaleFactor, changeY, changeX) {
var style = {};
style.transform = [
'rotate(' + rotation + 'deg)',
'scale(' + scaleFactor + ')',
'translateY(' + changeY + 'px)',
'translateX(' + changeX + 'px)'
].join(' ');
return style;
};
$scope.clipIt = function () {
$scope.clipImage(img, $scope.changeX, $scope.changeY, $scope.canvasWidth, $scope.canvasHeight);
}
img.crossOrigin = "anonymous";
img.src = "https://dl.dropboxusercontent.com/u/139992952/stackoverflow/faces.png";
$scope.clipImage = function(image, clipX, clipY, clipWidth, clipHeight) {
console.log('clipImage()', arguments, $scope.rotationAngle);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
if($scope.rotationAngle) {
// ctx.translate(0,0); // ps. this kinda worked
ctx.translate($scope.changeX, $scope.changeY); // moving the origin of the coordinate system to the current rendering context
ctx.translate($scope.imgWidth/2, $scope.imgHeight/2);
ctx.rotate(($scope.rotationAngle * (Math.PI / 180)));
ctx.translate(-$scope.changeX, -$scope.changeY);
ctx.translate(-$scope.imgWidth/2, -$scope.imgHeight/2);
}
if($scope.scaleFactor) {
ctx.scale($scope.scaleFactor, $scope.scaleFactor);
}
ctx.drawImage(
image,
-clipX,
-clipY,
clipWidth,
clipHeight,
clipX,
clipY,
clipWidth,
clipHeight
);
ctx.restore();
// var clippedImg = document.getElementById("clipped");
// clippedImg.src = canvas.toDataURL();
}
}]);

Related

How to change font color based on background image with javascript?

I want to change the font color based on the color of the image. The font color must be black or white, but it should change proportionally to the color of the image as it does in the code below.
So, I have this js function that if you move the mouse it changes the background color and consequently also the text (in the snippet move the pointer under the background). Obviously the part where you move the mouse to change color doesn't interest me, it's just a test. Is there a way to apply the function to my personal div?
In simple terms I want the color of the text to change based on my background and not if you move the mouse. Sorry for the poor explanation, I'm relatively new here, trying to learn how to exercise this function. Currently I don't know how to do it, I appreciate any answer, thanks.
function getTextColor(rgba){
rgba = rgba.match(/\d+/g);
if((rgba[0]*0.299)+(rgba[1]*0.587)+(rgba[2]*0.114)>186) {
return 'black';
} else {
return 'white';
}
}
var div = document.createElement('div');
div.style.height = '100vh';
document.body.appendChild(div);
div.addEventListener('mousemove', (event)=>{
var x = event.clientX;
var y = event.clientY;
div.textContent = `${x} , ${y}`;
div.style.backgroundColor = `rgba(${x},${y},100,100)`;
div.style.color = getTextColor(div.style.backgroundColor);
});
.background {
height: 100vh;
background: url("https://i.pinimg.com/originals/bc/a3/2d/bca32d5cdfabeaeb4faeb12bff160524.jpg");
}
<div class="background">Background example</div>
Explanation
Here is an example showing how to get the average using a canvas rendered to a 1x1-px scale. From there we set the header background and then apply a light or dark class based on the luminance of the aforementioned average.
Notes
Note 1:
There is some extra code to allow for easier visualization, this is commented and can be removed.
Note 2: The below code is not guaranteed to run on all browsers. Please see this thread for more specifics.
Note 3: This code only works with local images and CORS-enabled image URLs due to it's reliance on canvas.drawImage. Please see this for more information.
Example 1:
this example shows the functionality. It uses two image URLs in the JS to toggle between.
/*
THE TOGGLE ACTION
*/
/* The urls for toggling between */
const urlLight = 'https://images.unsplash.com/photo-1484503793037-5c9644d6a80a?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=930&q=80';
const urlDark = 'https://images.unsplash.com/photo-1517999144091-3d9dca6d1e43?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=627&q=80';
let currentUrl = urlLight;
const toggle = document.getElementById('toggle');
toggle.addEventListener("click", function() {
if (currentUrl === urlLight) {
currentUrl = urlDark;
} else {
currentUrl = urlLight;
}
getImageBrightness(currentUrl, function(brightness) {
const header = document.getElementById("header");
header.style.backgroundImage = `url(${currentUrl}`;
header.classList.remove("dark");
header.classList.remove("light");
console.log(brightness);
if (brightness > 225 / 2) {
header.classList.toggle("dark");
} else {
header.classList.toggle("light");
}
});
});
/*
Important get brightness code
*/
function getImageBrightness(imageSrc, callback) {
var img = document.createElement("img");
img.src = imageSrc;
img.style.display = "none";
img.crossOrigin = "anonymous";
document.body.appendChild(img);
var colorSum = 0;
img.onload = function() {
// create canvas
var canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
var r, g, b, avg;
for (var x = 0, len = data.length; x < len; x += 4) {
r = data[x];
g = data[x + 1];
b = data[x + 2];
avg = Math.floor((r + g + b) / 3);
colorSum += avg;
}
var brightness = Math.floor(colorSum / (this.width * this.height));
callback(brightness);
}
}
getImageBrightness(currentUrl, function(brightness) {
const header = document.getElementById("header");
header.style.backgroundImage = `url(${currentUrl}`;
header.classList.remove("dark");
header.classList.remove("light");
if (brightness > 225 / 2) {
header.classList.toggle("dark");
} else {
header.classList.toggle("light");
}
});
.dark {
color: black;
}
.light {
color: white;
}
* {
text-align: center;
}
#header {
padding: 2rem 0;
font-size: 4rem;
background-size: cover;
margin-bottom: 1rem;
background-position: center center;
}
<div id="header">
Header
</div>
<button id='toggle'>
Toggle Background
</button>
Example 2:
This example directly answers the question by retrieving the background image of the current div and running the function using said image.
/*
Important get brightness code
*/
function getImageBrightness(imageSrc, callback) {
var img = document.createElement("img");
img.src = imageSrc;
img.style.display = "none";
img.crossOrigin = "anonymous";
document.body.appendChild(img);
var colorSum = 0;
img.onload = function() {
// create canvas
var canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
var r, g, b, avg;
for (var x = 0, len = data.length; x < len; x += 4) {
r = data[x];
g = data[x + 1];
b = data[x + 2];
avg = Math.floor((r + g + b) / 3);
colorSum += avg;
}
var brightness = Math.floor(colorSum / (this.width * this.height));
callback(brightness);
}
}
/* The element we wish to work on */
const header = document.getElementById("header");
/* To get the background image. Get style and then background image with a slice to remove quotes */
var imageElement = document.getElementById('header'),
style = imageElement.currentStyle || window.getComputedStyle(imageElement, false),
backgroundImage = style.backgroundImage.slice(4, -1).replace(/"/g, "");
getImageBrightness(backgroundImage, function(brightness) {
/* Remove dark and light classes from the element */
header.classList.remove("dark");
header.classList.remove("light");
/* check brightness and apply correct style */
/* Please modify the below brightness comparison statement to adjust to your needs */
if (brightness > 225 / 2) {
header.classList.toggle("dark");
} else {
header.classList.toggle("light");
}
});
.dark {
color: black;
}
.light {
color: white;
}
* {
text-align: center;
}
#header {
padding: 2rem 0;
font-size: 4rem;
background-size: cover;
margin-bottom: 1rem;
background-position: center center;
background-image: url('https://images.unsplash.com/photo-1530128118208-89f6ce02b37b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1740&q=80')
}
<div id="header">
<h1>
Header
</h1>
</div>

4 animated SVGs in one HTML file using Animate CC

http://christianluneborg.com/dev/animation/icon-global.html
How do I load 4 separated animated SVGs in one JS/HTML files exported from Animate CC? I have created 1 animated SVG and it exports 3 different JS in one HTML. Is there a way I can reuse JS for other 3 icon SVGs without messing up the code? I know its not a good practice to load a bunch of JS files for each animated SVGs.
Just for 1 animated SVG (JS)
<script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script>
<script src="icon-skyscrapers.js"></script>
<script>
var canvas, stage, exportRoot, anim_container, dom_overlay_container,
fnStartAnimation;
function init() {
canvas = document.getElementById("canvas");
anim_container = document.getElementById("animation_container");
dom_overlay_container = document.getElementById("dom_overlay_container");
var comp=AdobeAn.getComposition("C1F9C7BD5BEEC941A1FE079EA94C1BF3");
var lib=comp.getLibrary();
handleComplete({},comp);
}
function handleComplete(evt,comp) {
//This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage.
var lib=comp.getLibrary();
var ss=comp.getSpriteSheet();
exportRoot = new lib.iconskyscrapers();
stage = new lib.Stage(canvas);
//Registers the "tick" event listener.
fnStartAnimation = function() {
stage.addChild(exportRoot);
createjs.Ticker.setFPS(lib.properties.fps);
createjs.Ticker.addEventListener("tick", stage)
stage.addEventListener("tick", handleTick)
function getProjectionMatrix(totalDepth) {
var focalLength = 528.25;
var projectionCenter = { x : lib.properties.width/2, y : lib.properties.height/2 };
var scale = (totalDepth + focalLength)/focalLength;
var scaleMat = new createjs.Matrix2D;
scaleMat.a = 1/scale;
scaleMat.d = 1/scale;
var projMat = new createjs.Matrix2D;
projMat.tx = -projectionCenter.x;
projMat.ty = -projectionCenter.y;
projMat = projMat.prependMatrix(scaleMat);
projMat.tx += projectionCenter.x;
projMat.ty += projectionCenter.y;
return projMat;
}
function handleTick(event) {
var focalLength = 528.25;
var cameraInstance = exportRoot.___camera___instance;
if(cameraInstance !== undefined && cameraInstance.pinToObject !== undefined)
{
cameraInstance.x = cameraInstance.pinToObject.x + cameraInstance.pinToObject.pinOffsetX;
cameraInstance.y = cameraInstance.pinToObject.y + cameraInstance.pinToObject.pinOffsetY;
if(cameraInstance.pinToObject.parent !== undefined && cameraInstance.pinToObject.parent.depth !== undefined)
cameraInstance.depth = cameraInstance.pinToObject.parent.depth + cameraInstance.pinToObject.pinOffsetZ;
}
for(child in exportRoot.children)
{
var layerObj = exportRoot.children[child];
if(layerObj == cameraInstance)
continue;
if(layerObj.currentFrame != layerObj.parent.currentFrame)
{
layerObj.gotoAndPlay(layerObj.parent.currentFrame);
}
var matToApply = new createjs.Matrix2D;
var cameraMat = new createjs.Matrix2D;
var totalDepth = layerObj.layerDepth ? layerObj.layerDepth : 0;
var cameraDepth = 0;
if(cameraInstance && !layerObj.isAttachedToCamera)
{
var stageCenter = { 'x' : lib.properties.width/2, 'y' : lib.properties.height/2 };
var mat = cameraInstance.getMatrix();
mat.tx -= stageCenter.x;
mat.ty -= stageCenter.y;
cameraMat = mat.invert();
cameraMat.prependTransform(stageCenter.x, stageCenter.y, 1, 1, 0, 0, 0, 0, 0);
cameraMat.appendTransform(-stageCenter.x, -stageCenter.y, 1, 1, 0, 0, 0, 0, 0);
if(cameraInstance.depth)
cameraDepth = cameraInstance.depth;
}
if(layerObj.depth)
{
totalDepth = layerObj.depth;
}
//Offset by camera depth
totalDepth -= cameraDepth;
if(totalDepth < -focalLength)
{
matToApply.a = 0;
matToApply.d = 0;
}
else
{
if(layerObj.layerDepth)
{
var sizeLockedMat = getProjectionMatrix(layerObj.layerDepth);
if(sizeLockedMat)
{
sizeLockedMat.invert();
matToApply.prependMatrix(sizeLockedMat);
}
}
matToApply.prependMatrix(cameraMat);
var projMat = getProjectionMatrix(totalDepth);
if(projMat)
{
matToApply.prependMatrix(projMat);
}
}
layerObj.transformMatrix = matToApply;
}
}
}
//Code to support hidpi screens and responsive scaling.
function makeResponsive(isResp, respDim, isScale, scaleType) {
var lastW, lastH, lastS=1;
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
function resizeCanvas() {
var w = lib.properties.width, h = lib.properties.height;
var iw = window.innerWidth, ih=window.innerHeight;
var pRatio = window.devicePixelRatio || 1, xRatio=iw/w, yRatio=ih/h, sRatio=1;
if(isResp) {
if((respDim=='width'&&lastW==iw) || (respDim=='height'&&lastH==ih)) {
sRatio = lastS;
}
else if(!isScale) {
if(iw<w || ih<h)
sRatio = Math.min(xRatio, yRatio);
}
else if(scaleType==1) {
sRatio = Math.min(xRatio, yRatio);
}
else if(scaleType==2) {
sRatio = Math.max(xRatio, yRatio);
}
}
canvas.width = w*pRatio*sRatio;
canvas.height = h*pRatio*sRatio;
canvas.style.width = dom_overlay_container.style.width = anim_container.style.width = w*sRatio+'px';
canvas.style.height = anim_container.style.height = dom_overlay_container.style.height = h*sRatio+'px';
stage.scaleX = pRatio*sRatio;
stage.scaleY = pRatio*sRatio;
lastW = iw; lastH = ih; lastS = sRatio;
stage.tickOnUpdate = false;
stage.update();
stage.tickOnUpdate = true;
}
}
makeResponsive(false,'both',false,1);
AdobeAn.compositionLoaded(lib.properties.id);
fnStartAnimation();
}
</script>
HTML
<body onload="init();" style="margin:0px;">
<div id="animation_container" style="background-color:rgba(255, 255, 255, 1.00); width:113px; height:84px">
<canvas id="canvas" width="113" height="84" style="position: absolute; display: block; background-color:rgba(255, 255, 255, 1.00);"></canvas>
<div id="dom_overlay_container" style="pointer-events:none; overflow:hidden; width:113px; height:84px; position: absolute; left: 0px; top: 0px; display: block;">
</div>
</div>
</body>

How do I get the full canvas content (even the hidden ones) with Javascript?

I am currently working on a Javascript project and I am struggling with exporting the entire SVG image on the canvas. So far I've been only able to export the visible part of the canvas, with out the "hidden" parts.
How do I capture the full canvas content?
Is there a way to do it without messing around with the original canvas size?
I am using D3.js V3
Screenshot of my project
Here's my code:
var svgString;
window.onload = function(){
setTimeout(function() {
exportSVG = document.getElementById("canvas");
document.getElementById("canvas").style.fontFamily= "lato";
document.getElementById("canvas").style.width= exportSVG.getBBox().width * 1;
document.getElementById("canvas").style.height= exportSVG.getBBox().height * 1;
svgString = getSVGString(exportSVG);
console.log(exportSVG.getBBox().width + " / " + exportSVG.getBBox().height);
svgString2Image(svgString, exportSVG.getBBox().width, exportSVG.getBBox().height, 'png', save); // passes Blob and filesize String to the callback
console.log("svg export code loaded");
// console.log(svgString.getBBox().width); document.getElementById("canvas").getBBox().width
}, 5000);
};
function save(dataBlob, filesize) {
saveAs(dataBlob, 'D3 vis exported to PNG.png'); // FileSaver.js function
}
// Below are the functions that handle actual exporting:
// getSVGString ( svgNode ) and svgString2Image( svgString, width, height, format, callback )
function getSVGString(svgNode) {
svgNode.setAttribute('xlink', 'http://www.w3.org/1999/xlink');
var cssStyleText = getCSSStyles(svgNode);
appendCSS(cssStyleText, svgNode);
var serializer = new XMLSerializer();
var svgString = serializer.serializeToString(svgNode);
svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace
svgString = svgString.replace(/NS\d+:href/g, 'xlink:href'); // Safari NS namespace fix
return svgString;
function getCSSStyles(parentElement) {
var selectorTextArr = [];
// Add Parent element Id and Classes to the list
selectorTextArr.push('#' + parentElement.id);
for (var c = 0; c < parentElement.classList.length; c++)
if (!contains('.' + parentElement.classList[c], selectorTextArr))
selectorTextArr.push('.' + parentElement.classList[c]);
// Add Children element Ids and Classes to the list
var nodes = parentElement.getElementsByTagName("*");
for (var i = 0; i < nodes.length; i++) {
var id = nodes[i].id;
if (!contains('#' + id, selectorTextArr))
selectorTextArr.push('#' + id);
var classes = nodes[i].classList;
for (var c = 0; c < classes.length; c++)
if (!contains('.' + classes[c], selectorTextArr))
selectorTextArr.push('.' + classes[c]);
}
// Extract CSS Rules
var extractedCSSText = "";
for (var i = 0; i < document.styleSheets.length; i++) {
var s = document.styleSheets[i];
try {
if (!s.cssRules) continue;
} catch (e) {
if (e.name !== 'SecurityError') throw e; // for Firefox
continue;
}
var cssRules = s.cssRules;
for (var r = 0; r < cssRules.length; r++) {
if (contains(cssRules[r].selectorText, selectorTextArr))
extractedCSSText += cssRules[r].cssText;
}
}
return extractedCSSText;
function contains(str, arr) {
return arr.indexOf(str) === -1 ? false : true;
}
}
function appendCSS(cssText, element) {
var styleElement = document.createElement("style");
styleElement.setAttribute("type", "text/css");
styleElement.innerHTML = cssText;
var refNode = element.hasChildNodes() ? element.children[0] : null;
element.insertBefore(styleElement, refNode);
}
}
function svgString2Image(svgString, width, height, format, callback) {
var format = format ? format : 'png';
var imgsrc = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgString))); // Convert SVG string to data URL
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
var image = new Image();
image.onload = function() {
context.clearRect(0, 0, width, height);
context.drawImage(image, 0, 0, width, height);
canvas.toBlob(function(blob) {
var filesize = Math.round(blob.length / 1024) + ' KB';
if (callback) callback(blob, filesize);
});
};
image.src = imgsrc;
}
Simply change your <svg> viewBox attribute before you serialize it to a string so that it displays everything:
var svg = document.querySelector('svg');
var toExport = svg.cloneNode(true); // avoids having to reset everything afterward
// grab its inner content BoundingBox
var bb = svg.getBBox();
// update its viewBox so it displays all its inner content
toExport.setAttribute('viewBox', bb.x + ' ' + bb.y + ' ' + bb.width + ' ' + bb.height);
toExport.setAttribute('width', bb.width);
toExport.setAttribute('height', bb.height);
var svgAsStr = new XMLSerializer().serializeToString(toExport);
var blob = new Blob([svgAsStr], {type: 'image/svg+xml'});
var img = new Image();
img.onload = drawToCanvas;
img.src = URL.createObjectURL(blob);
function drawToCanvas(evt) {
var canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
canvas.getContext('2d').drawImage(this, 0,0);
document.body.appendChild(canvas);
}
svg{border: 1px solid blue}
canvas{border: 1px solid green}
<svg width="50" height="50" viewBox="0 0 50 50">
<rect x="0" y="0" width="200" height="50" fill="#CCC"/>
</svg>

How to crop an image with jquery?

Can I crop an image without a canvas? And how to crop an image without resizing the image? Like this real picture to be 133px x 133px
Large Image to be Small Image
Large Image To be Small Image
And thiis my code https://jsfiddle.net/w26La1u6/2/
$(document).on('change', '#files', function(event) {
var files = event.target.files; // FileList object
var output = document.getElementById("list");
for (var i = 0, f; f = files[i]; i++) {
if (f.type.match('image.*')) {
if (this.files[0].size < 12097152) {
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
var span = document.createElement('span');
span.innerHTML = ['<img class="thumbnail" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'
].join('');
output.insertBefore(span, null);
};
})(f);
$('#clear, #list').show();
reader.readAsDataURL(f);
} else {
alert("Image Size is too big. Minimum size is 2MB.");
$(this).val("");
}
}
}
})
But if there is no other way to crop without canvas, tell me how to crop with canvas
EDIT
<input id="uploadImage" type="file" accept="image/*" capture="camera" />
<img id="imgDisplay" src="http://placehold.it/300x200" alt="Not a kitten" />
var Resample = (function (canvas) {
// (C) WebReflection Mit Style License
function Resample(img, width, height, onresample) {
var load = typeof img == "string",
i = load || img;
if (load) {
i = new Image;
// with propers callbacks
i.onload = onload;
i.onerror = onerror;
}
i._onresample = onresample;
i._width = width;
i._height = height;
load ? (i.src = img) : onload.call(img);
}
function onerror() {
throw ("not found: " + this.src);
}
function onload() {
var
img = this,
width = img._width,
height = img._height,
onresample = img._onresample
;
// Altered section - crop prior to resizing
var imgRatio = img.width / img.height;
var desiredRatio = width / height;
var cropWidth, cropHeight;
if (desiredRatio < imgRatio) {
cropHeight = img.height;
cropWidth = img.height * desiredRatio;
} else {
cropWidth = img.width;
cropHeight = img.width / desiredRatio;
}
delete img._onresample;
delete img._width;
delete img._height;
canvas.width = width;
canvas.height = height;
context.drawImage(
// original image
img,
// starting x point
0,
// starting y point
0,
// crop width
cropWidth,
// crop height
cropHeight,
// destination x point
0,
// destination y point
0,
// destination width
width,
// destination height
height
);
onresample(canvas.toDataURL("image/png"));
}
var context = canvas.getContext("2d"),
round = Math.round;
return Resample;
}(
this.document.createElement("canvas"))
);
var newCropWidth = 133;
var newCropHeight = 133;
function loadImage(data) {
document.querySelector('#imgDisplay').src = data;
}
function handleFileSelect(evt) {
if (evt.target.files.length === 1) {
var picFile = evt.target.files[0];
if (picFile.type.match('image.*')) {
var fileTracker = new FileReader;
fileTracker.onload = function() {
Resample(
this.result,
newCropWidth,
newCropHeight,
loadImage
);
}
fileTracker.readAsDataURL(picFile);
}
}
}
document.querySelector('#uploadImage').addEventListener('change', handleFileSelect, false);
There are ways to do it using jQuery UI but you can just utilize a plugin that someone else already made such as Cropper

How to add tooltip on draggable objects within Canvas?

In my code SVG is parse and drawn on Canvas and also orange1.png and green1.png images are plotted on SVg file. In this I am able to zoom and Pan canvas and also able to drag images which are plotted on it through JSON.
Now I want to add tooltip on the images (orange1.png and green1.png) When I click on those images or mouseover on those images.
showTooltip function is for showing the tooltip on those images(orange1.png , green1.png).
clearTooltip function is for clearing the tooltip.
Where and how should I add showTooltip and clearTooltip function in my updated code?
And which option will be better mouse click or mosehover for showing tooltip?
I tried some possibilities but I am missing something.
function showTooltip(x, y, index) {
var editedValue = [];
if (tooltip === null) {
tooltip = document.createElement('div');
tooltip.className = 'tooltip';
tooltip.style.left = (x) + 'px';
tooltip.style.top = (y) + 'px';
tooltip.innerHTML = "<input type='text' id='generic_txt' value='"+dataJSON[index].tooltiptxt[0]+"' /> <input type='submit' id='generic_edit' value='Edit'>"
document.getElementsByTagName('body')[0].appendChild(tooltip);
}
document.getElementById('generic_txt').setAttribute('disabled', 'disabled');
$("#generic_edit").click(function(){
if(document.getElementById('generic_edit').value == "Edit"){
document.getElementById('generic_txt').removeAttribute('disabled');
document.getElementById('generic_txt').focus();
document.getElementById('generic_edit').value = "Change";
} else {
document.getElementById('generic_txt').setAttribute('disabled', 'disabled');
document.getElementById('generic_edit').value = "Edit";
editedValue = $('#generic_txt').val();
dataJSON[index].tooltiptxt[0] = editedValue; // important line
}
return false;
});
}
function clearTooltip(doFade) {
if (tooltip !== null) {
var fade = 1;
function fadeOut() {
tooltip.style.opacity = fade;
fade -= 0.1;
if (fade > 0) {
setTimeout(fadeOut, 16);
} else {
remove();
}
}
function remove() {
document.getElementsByTagName('body')[0].removeChild(tooltip);
tooltip = null;
}
if (doFade === true) {
fadeOut();
//$('.first_cancel').click(fadeOut());
} else {
remove();
}
}
}
Following is my updated source code.
HTML Code :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<style>
canvas {
border:1px solid #000
}
.tooltip{
*position:fixed;
position:absolute;
*background:#ff7;
background:green;
border:1px solid #000;
padding:7px;
font-family:sans-serif;
font-size:12px;
}
.tooltip2 {
*position:fixed;
position:absolute;
background:pink;
border:1px solid #000;
padding:7px;
font-family:sans-serif;
font-size:12px;
}
</style>
</head>
<body>
<script src="http://canvg.googlecode.com/svn/trunk/rgbcolor.js"></script>
<script src="http://canvg.googlecode.com/svn/trunk/StackBlur.js"></script>
<script src="http://canvg.googlecode.com/svn/trunk/canvg.js"></script>
<canvas id="myCanvas" width="800" height="700" style="border: 1px solid;margin-top: 10px;"></canvas>
<div id="buttonWrapper">
<input type="button" id="plus" value="+">
<input type="button" id="minus" value="-">
<input type="button" id="original_size" value="100%">
</div>
<script src="/static/js/markers.js"></script>
<script src="/static/js/draw.js"></script>
</body>
</html>
draw.js:
var dataJSON = data || [];
var dataJSON2 = data2 || [];
window.onload = function(){
//$(function(){
var canvas=document.getElementById("myCanvas");
var ctx=canvas.getContext("2d");
var canvasOffset=$("#myCanvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var lastX=0;
var lastY=0;
var panX=0;
var panY=0;
var dragging=[];
var dragging2=[];
var isDown=false;
function loadImages(sources, callback){
var images = {};
var loadImages = 0;
var numImages = 0;
//get num of sources
for(var i in sources){
numImages++;
}
for(var i in sources){
images[i] = new Image();
images[i].onload = function(){
if(++loadImages >= numImages){
callback(images);
}
};
images[i].src = sources[i];
}
}
var sources = {orange : '/static/images/orange1.png', green : '/static/images/green1.png'};
// load the tiger image
var svgfiles = ["/static/images/awesome_tiger.svg"];
/*var tiger=new Image();
tiger.onload=function(){
draw();
}
tiger.src="tiger.png";*/
function draw(scaleValue){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.drawSvg(svgfiles[0],panX,panY,400*scaleValue, 400*scaleValue);
//ctx.drawImage(tiger,panX,panY,tiger.width,tiger.height);
//ctx.scale(scaleValue, scaleValue);
loadImages(sources, function(images){
ctx.scale(scaleValue, scaleValue);
for(var i = 0, pos; pos = dataJSON[i]; i++) {
ctx.drawImage(images.orange, parseInt(parseInt(pos.x) + parseInt(panX / scaleValue)), parseInt(parseInt(pos.y) + parseInt(panY / scaleValue)), 20/scaleValue, 20/scaleValue);
}
for(var i = 0, pos; pos = dataJSON2[i]; i++) {
ctx.drawImage(images.green, parseInt(parseInt(pos.x) + parseInt(panX / scaleValue)), parseInt(parseInt(pos.y) + parseInt(panY / scaleValue)), 20/scaleValue, 20/scaleValue);
}
ctx.restore();
});
};
var scaleValue = 1;
var scaleMultiplier = 0.8;
draw(scaleValue);
var startDragOffset = {};
var mouseDown = false;
// add button event listeners
document.getElementById("plus").addEventListener("click", function(){
scaleValue /= scaleMultiplier;
//checkboxZoomPan();
draw(scaleValue);
}, false);
document.getElementById("minus").addEventListener("click", function(){
scaleValue *= scaleMultiplier;
//checkboxZoomPan();
draw(scaleValue);
}, false);
document.getElementById("original_size").addEventListener("click", function(){
scaleValue = 1;
//checkboxZoomPan();
draw(scaleValue);
}, false);
// create an array of any "hit" colored-images
function imagesHitTests(x,y){
// adjust for panning
x-=panX;
y-=panY;
// create var to hold any hits
var hits=[];
// hit-test each image
// add hits to hits[]
loadImages(sources, function(images){
for(var i = 0, pos; pos = dataJSON[i]; i++) {
if(x >= parseInt(pos.x * scaleValue) && x <= parseInt((pos.x * scaleValue) + 20) && y >= parseInt(pos.y * scaleValue) && y <= parseInt((pos.y * scaleValue) + 20)){
hits.push(i);
}
}
});
return(hits);
}
function imagesHitTests2(x,y){
// adjust for panning
//x-=panX;
//x = parseInt(x) - parseInt(panX);
// y-=panY;
x-=panX;
y-=panY;
// create var to hold any hits
var hits2=[];
// hit-test each image
// add hits to hits[]
loadImages(sources, function(images){
for(var i = 0, pos; pos = dataJSON2[i]; i++) {
//if(x > pos.x && x < parseInt(parseInt(pos.x) + parseInt(20)) && y > pos.y && y < parseInt(parseInt(pos.y) + parseInt(20))){
if(x >= parseInt(pos.x * scaleValue) && x <= parseInt((pos.x * scaleValue) + 20) && y >= parseInt(pos.y * scaleValue) && y <= parseInt((pos.y * scaleValue) + 20)){
hits2.push(i);
}
}
});
return(hits2);
}
function handleMouseDown(e){
// get mouse coordinates
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// set the starting drag position
lastX=mouseX;
lastY=mouseY;
// test if we're over any of the images
dragging=imagesHitTests(mouseX,mouseY);
dragging2=imagesHitTests2(mouseX,mouseY);
// set the dragging flag
isDown=true;
}
function handleMouseUp(e){
// clear the dragging flag
isDown=false;
}
function handleMouseMove(e){
// if we're not dragging, exit
if(!isDown){
return;
}
//get mouse coordinates
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// calc how much the mouse has moved since we were last here
var dx=mouseX-lastX;
var dy=mouseY-lastY;
// set the lastXY for next time we're here
lastX=mouseX;
lastY=mouseY;
// handle drags/pans
if(dragging.length>0){
// we're dragging images
// move all affected images by how much the mouse has moved
for(var i = 0, pos; pos = dataJSON[dragging[i]]; i++) {
pos.x = parseInt(pos.x) + parseInt(dx);
pos.y = parseInt(pos.y) + parseInt(dy);
}
}
else if(dragging2.length>0){
for(var i = 0, pos1; pos1 = dataJSON2[dragging2[i]]; i++) {
pos1.x = parseInt(pos1.x) + parseInt(dx);
pos1.y = parseInt(pos1.y) + parseInt(dy);
}
}
else{
// we're panning the tiger
// set the panXY by how much the mouse has moved
panX+=dx;
panY+=dy;
}
draw(scaleValue);
}
// use jQuery to handle mouse events
$("#myCanvas").mousedown(function(e){handleMouseDown(e);});
$("#myCanvas").mousemove(function(e){handleMouseMove(e);});
$("#myCanvas").mouseup(function(e){handleMouseUp(e);});
// }); // end $(function(){});
}
markers.js:
data = [
{ "id" :["first"],
"x": ["195"],
"y": ["150"],
"tooltiptxt": ["Region 1"]
},
{
"id" :["second"],
"x": ["255"],
"y": ["180"],
"tooltiptxt": ["Region 2"]
},
{
"id" :["third"],
"x": ["200"],
"y": ["240"],
"tooltiptxt": ["Region 3"]
}
];
data2 = [
{ "id" :["first2"],
"x": ["225"],
"y": ["150"],
"tooltiptxt": ["Region 21"]
},
{
"id" :["second2"],
"x": ["275"],
"y": ["180"],
"tooltiptxt": ["Region 22"]
},
{
"id" :["third3"],
"x": ["300"],
"y": ["240"],
"tooltiptxt": ["Region 23"]
}
];
I think you can try out this :
<!DOCTYPE html>
<html>
<head>
<title>Canvas Links Example</title>
<script>
function OnLoad(){
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.translate(0.5, 0.5);
ctx.strokeStyle = "#5F7FA2";
ctx.strokeRect(50, 50, 25, 25);
var img = new Image();
img.src = "http://www.cs.washington.edu/education/courses/csep576/05wi/projects/project4/web/artifact/liebling/average_face.gif";
var img1 = new Image();
img1.src = "E:\Very IMP Projects\WinService\SourceCode\MVC\BpmPresentation\Images\loading.gif";
img.onload = function(){
ctx.drawImage(img, 50, 50);
canvas.addEventListener("mousemove", on_mousemove, false);
canvas.addEventListener("click", on_click, false);
Links.push(50 + ";" + 50 + ";" + 25 + ";" + 25 + ";" + "http://plus.google.com/");
}
var Links = new Array();
var hoverLink = "";
var canvas1 = document.getElementById("myCanvas1");
var ctx1 = canvas1.getContext("2d");
function on_mousemove (ev) {
var x, y;
if (ev.layerX || ev.layerX == 0) { // For Firefox
x = ev.layerX;
y = ev.layerY;
}
for (var i = Links.length - 1; i >= 0; i--) {
var params = new Array();
params = Links[i].split(";");
var linkX = parseInt(params[0]),
linkY = parseInt(params[1]),
linkWidth = parseInt(params[2]),
linkHeight = parseInt(params[3]),
linkHref = params[4];
if (x >= linkX && x <= (linkX + linkWidth) && y >= linkY && y <= (linkY + linkHeight)){
document.body.style.cursor = "pointer";
hoverLink = linkHref;
ctx1.translate(0.5, 0.5);
ctx1.strokeStyle = "#5F7FA2";
canvas1.style.left = x + "px";
canvas1.style.top = (y+40) + "px";
ctx1.clearRect(0, 0, canvas1.width, canvas1.height);
var img1 = new Image();
img1.src = "E:\Very IMP Projects\WinService\SourceCode\MVC\BpmPresentation\Images\loading.gif";
img1.onload = function () {
ctx1.drawImage(img1, 50, 50);
}
break;
}
else {
document.body.style.cursor = "";
hoverLink = "";
canvas1.style.left = "-200px";
}
};
}
function on_click(e) {
if (hoverLink) {
window.open(hoverLink);
//window.location = hoverLink;
}
}
}
</script>
</head>
<body onload="OnLoad();">
<canvas id="myCanvas" width="450" height="250" style="border:1px solid #eee;">
Canvas is not supported in your browser ! :(
</canvas>
<canvas id="myCanvas1" width="50" height="50" style="background-color:white;border:1px solid blue;position:absolute;left:-200px;top:100px;">
</canvas>
</body>
</html>

Categories