jQuery('#carregar').click(function() {
var canvas = document.getElementById('canvas');
var image = document.getElementById('image');
var element = canvas.getContext("2d");
element.clearRect(0, 0, canvas.width, canvas.height);
element.drawImage(image, 0, 0, 300, 300);
});
jsfiddle.net/braziel/nWyDE/
I have a problem to rotate an image 90 ° to the right or to the left.
I use an image on the canvas, the same screen will have several canvas equal to that of the example, but I left it as close as possible to the project.
I ask, how do I rotate the image 90 ° to the left or right when I click "Rotate Left" and "Rotate Right"?
I tried several codes on the internet but none worked.
You can use canvas’ context.translate & context.rotate to do rotate your image
Here’s a function to draw an image that is rotated by the specified degrees:
function drawRotated(degrees){
context.clearRect(0,0,canvas.width,canvas.height);
// save the unrotated context of the canvas so we can restore it later
// the alternative is to untranslate & unrotate after drawing
context.save();
// move to the center of the canvas
context.translate(canvas.width/2,canvas.height/2);
// rotate the canvas to the specified degrees
context.rotate(degrees*Math.PI/180);
// draw the image
// since the context is rotated, the image will be rotated also
context.drawImage(image,-image.width/2,-image.width/2);
// we’re done with the rotating so restore the unrotated context
context.restore();
}
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/6ZsCz/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var angleInDegrees=0;
var image=document.createElement("img");
image.onload=function(){
ctx.drawImage(image,canvas.width/2-image.width/2,canvas.height/2-image.width/2);
}
image.src="houseicon.png";
$("#clockwise").click(function(){
angleInDegrees+=30;
drawRotated(angleInDegrees);
});
$("#counterclockwise").click(function(){
angleInDegrees-=30;
drawRotated(angleInDegrees);
});
function drawRotated(degrees){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.translate(canvas.width/2,canvas.height/2);
ctx.rotate(degrees*Math.PI/180);
ctx.drawImage(image,-image.width/2,-image.width/2);
ctx.restore();
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas><br>
<button id="clockwise">Rotate right</button>
<button id="counterclockwise">Rotate left</button>
</body>
</html>
Quickest 2D context image rotation method
A general purpose image rotation, position, and scale.
// no need to use save and restore between calls as it sets the transform rather
// than multiply it like ctx.rotate ctx.translate ctx.scale and ctx.transform
// Also combining the scale and origin into the one call makes it quicker
// x,y position of image center
// scale scale of image
// rotation in radians.
function drawImage(image, x, y, scale, rotation){
ctx.setTransform(scale, 0, 0, scale, x, y); // sets scale and origin
ctx.rotate(rotation);
ctx.drawImage(image, -image.width / 2, -image.height / 2);
}
If you wish to control the rotation point use the next function
// same as above but cx and cy are the location of the point of rotation
// in image pixel coordinates
function drawImageCenter(image, x, y, cx, cy, scale, rotation){
ctx.setTransform(scale, 0, 0, scale, x, y); // sets scale and origin
ctx.rotate(rotation);
ctx.drawImage(image, -cx, -cy);
}
To reset the 2D context transform
ctx.setTransform(1,0,0,1,0,0); // which is much quicker than save and restore
Thus to rotate image to the left (anti clockwise) 90 deg
drawImage(image, canvas.width / 2, canvas.height / 2, 1, - Math.PI / 2);
Thus to rotate image to the right (clockwise) 90 deg
drawImage(image, canvas.width / 2, canvas.height / 2, 1, Math.PI / 2);
Example draw 500 images translated rotated scaled
var image = new Image;
image.src = "https://i.stack.imgur.com/C7qq2.png?s=328&g=1";
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.style.position = "absolute";
canvas.style.top = "0px";
canvas.style.left = "0px";
document.body.appendChild(canvas);
var w,h;
function resize(){ w = canvas.width = innerWidth; h = canvas.height = innerHeight;}
resize();
window.addEventListener("resize",resize);
function rand(min,max){return Math.random() * (max ?(max-min) : min) + (max ? min : 0) }
function DO(count,callback){ while (count--) { callback(count) } }
const sprites = [];
DO(500,()=>{
sprites.push({
x : rand(w), y : rand(h),
xr : 0, yr : 0, // actual position of sprite
r : rand(Math.PI * 2),
scale : rand(0.1,0.25),
dx : rand(-2,2), dy : rand(-2,2),
dr : rand(-0.2,0.2),
});
});
function drawImage(image, spr){
ctx.setTransform(spr.scale, 0, 0, spr.scale, spr.xr, spr.yr); // sets scales and origin
ctx.rotate(spr.r);
ctx.drawImage(image, -image.width / 2, -image.height / 2);
}
function update(){
var ihM,iwM;
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0,0,w,h);
if(image.complete){
var iw = image.width;
var ih = image.height;
for(var i = 0; i < sprites.length; i ++){
var spr = sprites[i];
spr.x += spr.dx;
spr.y += spr.dy;
spr.r += spr.dr;
iwM = iw * spr.scale * 2 + w;
ihM = ih * spr.scale * 2 + h;
spr.xr = ((spr.x % iwM) + iwM) % iwM - iw * spr.scale;
spr.yr = ((spr.y % ihM) + ihM) % ihM - ih * spr.scale;
drawImage(image,spr);
}
}
requestAnimationFrame(update);
}
requestAnimationFrame(update);
The other solution works great for square images. Here is a solution that will work for an image of any dimension. The canvas will always fit the image rather than the other solution which may cause portions of the image to be cropped off.
var canvas;
var angleInDegrees=0;
var image=document.createElement("img");
image.onload=function(){
drawRotated(0);
}
image.src="http://greekgear.files.wordpress.com/2011/07/bob-barker.jpg";
$("#clockwise").click(function(){
angleInDegrees+=90 % 360;
drawRotated(angleInDegrees);
});
$("#counterclockwise").click(function(){
if(angleInDegrees == 0)
angleInDegrees = 270;
else
angleInDegrees-=90 % 360;
drawRotated(angleInDegrees);
});
function drawRotated(degrees){
if(canvas) document.body.removeChild(canvas);
canvas = document.createElement("canvas");
var ctx=canvas.getContext("2d");
canvas.style.width="20%";
if(degrees == 90 || degrees == 270) {
canvas.width = image.height;
canvas.height = image.width;
} else {
canvas.width = image.width;
canvas.height = image.height;
}
ctx.clearRect(0,0,canvas.width,canvas.height);
if(degrees == 90 || degrees == 270) {
ctx.translate(image.height/2,image.width/2);
} else {
ctx.translate(image.width/2,image.height/2);
}
ctx.rotate(degrees*Math.PI/180);
ctx.drawImage(image,-image.width/2,-image.height/2);
document.body.appendChild(canvas);
}
http://jsfiddle.net/6ZsCz/1588/
This is the simplest code to draw a rotated and scaled image:
function drawImage(ctx, image, x, y, w, h, degrees){
ctx.save();
ctx.translate(x+w/2, y+h/2);
ctx.rotate(degrees*Math.PI/180.0);
ctx.translate(-x-w/2, -y-h/2);
ctx.drawImage(image, x, y, w, h);
ctx.restore();
}
As #markE mention in his answer
the alternative is to untranslate & unrotate after drawing
It is much faster than context save and restore.
Here is an example
// translate and rotate
this.context.translate(x,y);
this.context.rotate(radians);
this.context.translate(-x,-y);
this.context.drawImage(...);
// untranslate and unrotate
this.context.translate(x, y);
this.context.rotate(-radians);
this.context.translate(-x,-y);
This is full degree image rotation code. I recommend you to check the below example app in the jsfiddle.
https://jsfiddle.net/casamia743/xqh48gno/
The process flow of this example app is
load Image, calculate boundaryRad
create temporary canvas
move canvas context origin to joint position of the projected rect
rotate canvas context with input degree amount
use canvas.toDataURL method to make image blob
using image blob, create new Image element and render
function init() {
...
image.onload = function() {
app.boundaryRad = Math.atan(image.width / image.height);
}
...
}
/**
* NOTE : When source rect is rotated at some rad or degrees,
* it's original width and height is no longer usable in the rendered page.
* So, calculate projected rect size, that each edge are sum of the
* width projection and height projection of the original rect.
*/
function calcProjectedRectSizeOfRotatedRect(size, rad) {
const { width, height } = size;
const rectProjectedWidth = Math.abs(width * Math.cos(rad)) + Math.abs(height * Math.sin(rad));
const rectProjectedHeight = Math.abs(width * Math.sin(rad)) + Math.abs(height * Math.cos(rad));
return { width: rectProjectedWidth, height: rectProjectedHeight };
}
/**
* #callback rotatedImageCallback
* #param {DOMString} dataURL - return value of canvas.toDataURL()
*/
/**
* #param {HTMLImageElement} image
* #param {object} angle
* #property {number} angle.degree
* #property {number} angle.rad
* #param {rotatedImageCallback} cb
*
*/
function getRotatedImage(image, angle, cb) {
const canvas = document.createElement('canvas');
const { degree, rad: _rad } = angle;
const rad = _rad || degree * Math.PI / 180 || 0;
debug('rad', rad);
const { width, height } = calcProjectedRectSizeOfRotatedRect(
{ width: image.width, height: image.height }, rad
);
debug('image size', image.width, image.height);
debug('projected size', width, height);
canvas.width = Math.ceil(width);
canvas.height = Math.ceil(height);
const ctx = canvas.getContext('2d');
ctx.save();
const sin_Height = image.height * Math.abs(Math.sin(rad))
const cos_Height = image.height * Math.abs(Math.cos(rad))
const cos_Width = image.width * Math.abs(Math.cos(rad))
const sin_Width = image.width * Math.abs(Math.sin(rad))
debug('sin_Height, cos_Width', sin_Height, cos_Width);
debug('cos_Height, sin_Width', cos_Height, sin_Width);
let xOrigin, yOrigin;
if (rad < app.boundaryRad) {
debug('case1');
xOrigin = Math.min(sin_Height, cos_Width);
yOrigin = 0;
} else if (rad < Math.PI / 2) {
debug('case2');
xOrigin = Math.max(sin_Height, cos_Width);
yOrigin = 0;
} else if (rad < Math.PI / 2 + app.boundaryRad) {
debug('case3');
xOrigin = width;
yOrigin = Math.min(cos_Height, sin_Width);
} else if (rad < Math.PI) {
debug('case4');
xOrigin = width;
yOrigin = Math.max(cos_Height, sin_Width);
} else if (rad < Math.PI + app.boundaryRad) {
debug('case5');
xOrigin = Math.max(sin_Height, cos_Width);
yOrigin = height;
} else if (rad < Math.PI / 2 * 3) {
debug('case6');
xOrigin = Math.min(sin_Height, cos_Width);
yOrigin = height;
} else if (rad < Math.PI / 2 * 3 + app.boundaryRad) {
debug('case7');
xOrigin = 0;
yOrigin = Math.max(cos_Height, sin_Width);
} else if (rad < Math.PI * 2) {
debug('case8');
xOrigin = 0;
yOrigin = Math.min(cos_Height, sin_Width);
}
debug('xOrigin, yOrigin', xOrigin, yOrigin)
ctx.translate(xOrigin, yOrigin)
ctx.rotate(rad);
ctx.drawImage(image, 0, 0);
if (DEBUG) drawMarker(ctx, 'red');
ctx.restore();
const dataURL = canvas.toDataURL('image/jpg');
cb(dataURL);
}
function render() {
getRotatedImage(app.image, {degree: app.degree}, renderResultImage)
}
I built an image uploader that resizes the image in the background, and also allows the user to rotate the image 90 degrees left or right. This isn't something that is solved with just a few lines of code, so you will want to checkout the jsfiddle https://jsfiddle.net/alienbush/z02jatnr/6/. I also included the complete code below.
The main drawing function looks like this:
let drawOptimizedImage = function (canvas, image, maxSize, rotationDirection) {
let degrees = updateRotationDegrees(rotationDirection)
let newSize = determineSize(image.width, image.height, maxSize.width, maxSize.height, degrees)
canvas.width = newSize.width
canvas.height = newSize.height
let ctx = canvas.getContext('2d')
ctx.save()
ctx.clearRect(0, 0, canvas.width, canvas.height)
if (degrees === 0) {
ctx.drawImage(image, 0, 0, newSize.width, newSize.height)
}
else {
ctx.translate(canvas.width / 2, canvas.height / 2)
ctx.rotate(degrees * Math.PI / 180)
if (Math.abs(degrees) === 180) {
ctx.drawImage(image, -newSize.width / 2, -newSize.height / 2, newSize.width, newSize.height)
}
else { // 90 or 270 degrees (values for width and height are swapped for these rotation positions)
ctx.drawImage(image, -newSize.height / 2, -newSize.width / 2, newSize.height, newSize.width)
}
}
ctx.restore()
}
Here's the complete code:
let imgPreview = document.getElementById('imgPreview')
let canvas = document.getElementById('canvas')
let statusMessage = document.getElementById('statusMessage')
let img = new Image
let maxSize = {
width: 800,
height: 600
}
let rotationDegrees = 0
// canvas.toBlob Polyfill from https://gist.github.com/salzhrani/02a6e807f24785a4d34b
if (!HTMLCanvasElement.prototype.toBlob) {
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value: function(callback, type, quality) {
var bin = atob(this.toDataURL(type, quality).split(',')[1]),
len = bin.length,
len32 = len >> 2,
a8 = new Uint8Array(len),
a32 = new Uint32Array(a8.buffer, 0, len32);
for (var i = 0, j = 0; i < len32; i++) {
a32[i] = bin.charCodeAt(j++) |
bin.charCodeAt(j++) << 8 |
bin.charCodeAt(j++) << 16 |
bin.charCodeAt(j++) << 24;
}
var tailLength = len & 3;
while (tailLength--) {
a8[j] = bin.charCodeAt(j++);
}
callback(new Blob([a8], {
'type': type || 'image/png'
}));
}
});
}
document.getElementById('fileInput').addEventListener('change', function(e) {
if (!e.target.files.length) {
return
}
let file = e.target.files[0]
if (isValidMIME(file, ['image/bmp', 'image/jpeg', 'image/png'])) {
img.src = window.URL.createObjectURL(file)
} else {
alert('Invalid file type. The image file must be one of the following: .jpg .jpeg .png .bmp')
}
})
let isValidMIME = function(file, MIMEtypes) {
for (let i = 0; i < MIMEtypes.length; i++) {
if (MIMEtypes[i] === file.type) {
return true
}
}
return false
}
img.addEventListener('load', function() {
rotationDegrees = 0
removeStatusMessage()
drawOptimizedImage(canvas, img, maxSize)
updateImgPreview(canvas, imgPreview)
})
let removeStatusMessage = function() {
statusMessage.textContent = ''
statusMessage.style.display = 'none'
}
let drawOptimizedImage = function(canvas, image, maxSize, rotationDirection) {
let degrees = updateRotationDegrees(rotationDirection)
let newSize = determineSize(image.width, image.height, maxSize.width, maxSize.height, degrees)
canvas.width = newSize.width
canvas.height = newSize.height
let ctx = canvas.getContext('2d')
ctx.save()
ctx.clearRect(0, 0, canvas.width, canvas.height)
if (degrees === 0) {
ctx.drawImage(image, 0, 0, newSize.width, newSize.height)
} else {
ctx.translate(canvas.width / 2, canvas.height / 2)
ctx.rotate(degrees * Math.PI / 180)
if (Math.abs(degrees) === 180) {
ctx.drawImage(image, -newSize.width / 2, -newSize.height / 2, newSize.width, newSize.height)
} else { // 90 or 270 degrees (values for width and height are swapped for these rotation positions)
ctx.drawImage(image, -newSize.height / 2, -newSize.width / 2, newSize.height, newSize.width)
}
}
ctx.restore()
}
let updateRotationDegrees = function(rotationDirection) {
if (rotationDirection === 'clockwise') {
rotationDegrees += 90
} else if (rotationDirection === 'anticlockwise') {
rotationDegrees -= 90
}
if (Math.abs(rotationDegrees) === 360) {
rotationDegrees = 0
}
return rotationDegrees
}
let determineSize = function(width, height, maxW, maxH, degrees) {
let w, h;
degrees = Math.abs(degrees)
if (degrees === 90 || degrees === 270) { // values for width and height are swapped for these rotation positions
w = height
h = width
} else {
w = width
h = height
}
if (w > h) {
if (w > maxW) {
h = h * maxW / w
w = maxW
}
} else {
if (h > maxH) {
w = w * maxH / h
h = maxH
}
}
return {
width: w,
height: h
}
}
let updateImgPreview = function(canvas, div) {
if (canvas.width < div.clientWidth && canvas.height < div.clientHeight) {
div.style.backgroundSize = 'auto'
} else {
div.style.backgroundSize = 'contain'
}
div.style.backgroundImage = 'url(' + canvas.toDataURL() + ')'
}
document.getElementById('clockwiseBtn').addEventListener('click', function() {
removeStatusMessage()
drawOptimizedImage(canvas, img, maxSize, 'clockwise')
updateImgPreview(canvas, imgPreview)
})
document.getElementById('anticlockwiseBtn').addEventListener('click', function() {
removeStatusMessage()
drawOptimizedImage(canvas, img, maxSize, 'anticlockwise')
updateImgPreview(canvas, imgPreview)
})
document.getElementById('uploadBtn').addEventListener('click', function() {
let fileInput = document.getElementById('fileInput')
if (!fileInput.files.length) {
alert('Please choose a file first');
return;
}
let formData = new FormData()
formData.append('fileName', 'yourCustomFileNameHere')
canvas.toBlob(function(blob) {
formData.append('image', blob)
let url = 'theURLtoSendTheFileTo'
sendForm(url, formData, doAfterUploadSuccess)
}, 'image/jpeg', 1.0)
})
let sendForm = function(url, formData, callback) {
// Simulating upload. Use the commented code below for a real upload.
statusMessage.style.display = 'block'
statusMessage.textContent = 'Uploading, please wait...'
setTimeout(callback, 2000)
// let xhr = new XMLHttpRequest()
// addUploadListeners(xhr)
// xhr.open('POST', url, true)
// xhr.onload = function () {
// if (xhr.status == 200) {
// if (callback) { callback(xhr) }
// }
// else if (xhr.status === 0) {
// alert('No response from server. Check network connection.')
// }
// else {
// alert('There was a problem uploading: ' + xhr.statusText)
// }
// }
// statusMessage.style.display = 'block'
// xhr.send(formData)
}
let addUploadListeners = function(xhr) {
xhr.addEventListener('loadstart', function(e) {
statusMessage.textContent = 'Uploading, please wait...'
})
xhr.addEventListener('abort', function(e) {
statusMessage.textContent = 'Aborted upload'
})
xhr.addEventListener('error', function(e) {
statusMessage.textContent = 'Error during upload'
})
}
let doAfterUploadSuccess = function(xhr) {
statusMessage.textContent = 'Success!'
}
body {
background-color: lightgray;
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 11pt;
font-weight: 400;
-webkit-font-smoothing: antialiased;
margin: 0;
}
button {
outline: none !important;
border-style: none;
background-color: rgb(115, 115, 250);
color: white;
padding: 10px 15px 12px 15px;
cursor: pointer;
border-radius: 2px;
font: inherit;
}
.canvas {
/* You can use display: none; to hide the canvas. The image will upload the same, whether or not the canvas is diplayed. */
display: block;
margin: 0px auto 40px auto;
}
.card {
background: white;
border-radius: 2px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.img-form {
padding: 15px 15px 0px 15px;
width: 320px;
margin: 0 auto;
}
.img-uploader-panel {
padding: 10px;
width: 340px;
margin: 0px auto 20px auto;
}
.img-uploader-header {
margin-top: 5px;
text-align: center;
}
.img-preview {
display: flex;
background-repeat: no-repeat;
background-position-x: center;
background-position-y: center;
background-size: contain;
border: 1px solid rgb(160, 160, 160);
width: 320px;
height: 320px;
margin: 0 auto;
}
.status-message {
display: none;
align-self: flex-end;
margin: 0;
line-height: 50px;
background-color: rgba(0, 0, 0, 0.5);
color: white;
width: 100%;
text-align: center;
}
.uploader-btn-panel {
display: flex;
padding-top: 10px;
justify-content: center;
align-items: center;
}
.rotate-btn {
font-size: 32px;
padding: 5px 12px 9px 13px;
margin-right: 10px;
background-color: transparent;
color: rgba(83, 83, 249, 1);
}
.clockwise-btn {
transform: rotate(90deg);
}
.anticlockwise-btn {
transform: rotate(270deg);
}
.upload-btn {
margin-left: 20px;
}
<form action="post" id="imgForm" class="img-form">
<label for="fileInput">Add an image:</label><br>
<input type="file" name="fileInput" id="fileInput" accept=".jpg, .jpeg, .png, .bmp">
</form><br>
<div class="img-uploader-panel card">
<p class="img-uploader-header">Image Preview</p>
<div id="imgPreview" class="img-preview">
<p id="statusMessage" class="status-message"></p>
</div>
<div class="uploader-btn-panel">
<button id="anticlockwiseBtn" class="anticlockwise-btn rotate-btn">↺</button>
<button id="clockwiseBtn" class="clockwise-btn rotate-btn">↻</button>
<button id="uploadBtn" class="upload-btn">Upload</button>
</div>
</div>
<canvas id="canvas" class="canvas"></canvas>
Here is Something I did
var ImgRotator = {
angle:parseInt(45),
image:{},
src:"",
canvasID:"",
intervalMS:parseInt(500),
jump:parseInt(5),
start_action:function(canvasID, imgSrc, interval, jumgAngle){
ImgRotator.jump = jumgAngle;
ImgRotator.intervalMS = interval;
ImgRotator.canvasID = canvasID;
ImgRotator.src = imgSrc ;
var image = new Image();
var canvas = document.getElementById(ImgRotator.canvasID);
image.onload = function() {
ImgRotator.image = image;
canvas.height = canvas.width = Math.sqrt( image.width* image.width+image.height*image.height);
window.setInterval(ImgRotator.keepRotating,ImgRotator.intervalMS);
//theApp.keepRotating();
};
image.src = ImgRotator.src;
},
keepRotating:function(){
ImgRotator.angle+=ImgRotator.jump;
var canvas = document.getElementById(ImgRotator.canvasID);
var ctx = canvas.getContext("2d");
ctx.save();
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.translate(canvas.width/2,canvas.height/2);
ctx.rotate(ImgRotator.angle*Math.PI/180);
ctx.drawImage(ImgRotator.image, -ImgRotator.image.width/2,-ImgRotator.image.height/2);
ctx.restore();
}
}
usage
ImgRotator.start_action("canva",
"data:image/jpeg;base64,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",
500,15
);
HTML
<canvas id="canva" width="350" height="350" style="border:solid thin black;"></canvas>
#Steve Farthing's answer is absolutely right.
But if you rotate more than 4 times then the image will get cropped from both the side.
For that you need to do like this.
$("#clockwise").click(function(){
angleInDegrees+=90 % 360;
drawRotated(angleInDegrees);
if(angleInDegrees == 360){ // add this lines
angleInDegrees = 0
}
});
Then you will get the desired result. Thanks. Hope this will help someone :)
Why not do it for the entire page. At page load detect all images and continuously rotate all of them.
var RotationCollection = {
rotators: [],
start_action: function (showBorders, isoverlap) {
try {
var canvasTemplate = '<canvas id="_ID_" width="350" height="350" ></canvas>';
var ja = 5;
$.each($("img"), function (index, val) {
var newID = "can_" + index;
var can = canvasTemplate.replace("_ID_", newID);
if (showBorders == true) $(can).insertAfter($(val)).css({ "border": "solid thin black", "box-shadow": "5px 5px 10px 2px black", "border-raduis": "15px" });
else $(can).insertAfter($(val));
$(val).remove();
var curRot = new RotationClass(newID, $(val).attr('src'), ja * ((0 == index % 2) ? -1 : 1), isoverlap);
RotationCollection.rotators[index] = curRot;
ja += 5;
//return false;
});
window.setInterval(function () {
$.each(RotationCollection.rotators, function (index, value) {
value.drawRotatedImage();
})
}, 500);
}
catch (err) {
console.log(err.message);
}
}
};
function RotationClass(canvasID, imgSrc, jumgAngle, overlap) {
var self = this;
self.overlap = overlap;
self.angle = parseInt(45);
self.image = {};
self.src = imgSrc;
self.canvasID = canvasID;
self.jump = parseInt(jumgAngle);
self.start_action = function () {
var image = new Image();
var canvas = document.getElementById(self.canvasID);
image.onload = function () {
self.image = image;
canvas.height = canvas.width = Math.sqrt(image.width * image.width + image.height * image.height);
self.drawRotatedImage(self);
};
image.src = self.src;
}
self.start_action();
this.drawRotatedImage = function () {
var self = this;
self.angle += self.jump;
var canvas = document.getElementById(self.canvasID);
var ctx = canvas.getContext("2d");
ctx.save();
if (self.overlap) ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.rotate(self.angle * Math.PI / 180);
ctx.drawImage(self.image, -self.image.width / 2, -self.image.height / 2);
ctx.restore();
}
}
var theApp = {
start_Action: function () {
RotationCollection.start_action(true, true);
}
};
$(document).ready(theApp.start_Action);
Please check out for theApp.start_Action where all action begins
The HTML can be as follows:
<p>
Deepika Padukone.<br />
<img alt="deepika" src="data:image/jpeg;base64,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" />
</p>
<p>
Priyanka Chopra.<br />
<img alt="Priyanka" src="data:image/jpeg;base64,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" />
</p>
Some options to overlap rotations, borders are also added
To rotate and fill (stretch to fit), try this fiddle which uses the corner of the canvas for a start point instead of the center and can rotate 90, 180 and 270 degrees.
Note: the fiddle is stretching a 200 * 300 image to fit a 600 * 650 canvas
const canvas = document.getElementById('canvas');
const image = document.getElementById('source');
const Rotation = {
None: 0,
Right: 90,
Flip: 180,
Left: 270
};
const noRotation = () => Rotate(Rotation.None);
const rotateRight = () => Rotate(Rotation.Right);
const rotateLeft = () => Rotate(Rotation.Left);
const flip = () => Rotate(Rotation.Flip);
const Rotate = (orientation) => rotateImage(canvas, image, orientation);
function rotateImage(canvas, image, rotation){
const rotate = correctRotation(rotation);
const context = canvas.getContext('2d');
let offsetX = 0;
let offsetY = 0;
let displacementX = canvas.width;
let displacementY = canvas.height;
if (rotate === Rotation.Left || rotate === Rotation.Right){
displacementX = canvas.height;
displacementY = canvas.width;
}
switch(rotate) {
case Rotation.Flip:
offsetX = canvas.width;
offsetY = canvas.height;
break;
case Rotation.Left:
offsetY = canvas.height;
break;
case Rotation.Right:
offsetX = canvas.width;
break;
}
context.setTransform(1, 0, 0, 1, offsetX, offsetY);
context.rotate(rotate * Math.PI / 180);
context.drawImage(image, 0,0, displacementX, displacementY )
}
function correctRotation(rotation) {
return !rotation ? Rotation.None
: rotation < Rotation.Flip ? Rotation.Right
: rotation < Rotation.Left ? Rotation.Flip
: Rotation.Left;
}
image.addEventListener('load', e => noRotation() );
https://jsfiddle.net/0unyh7ck/8/
I am using Bootstrap for a one-page website project. This website is divided in 4 parts, each one inside a 'section' with its own background color/image and content.
For one of these sections (the first one), which occupies the whole screen and has a 'Navbar' at the top and some headers inside, I would like to set a script as the background and not a simple image or solid color as in the other sections.
For this, I would like to know how to set a JavaScript code as the background, without affecting any other item inside the same section and being able to see the text over this background element.
This is the concrete script that I would like to set as background (got it from codePen.io): http://jsfiddle.net/oleg_korol/a1bxr5ua/1/
Here is the code:
var w = c.width = window.innerWidth,
h = c.height = window.innerHeight,
ctx = c.getContext('2d'),
opts = {
len: 20,
count: 50,
baseTime: 10,
addedTime: 10,
dieChance: .05,
spawnChance: 1,
sparkChance: .1,
sparkDist: 10,
sparkSize: 2,
color: 'hsl(hue,100%,light%)',
baseLight: 50,
addedLight: 10, // [50-10,50+10]
shadowToTimePropMult: 6,
baseLightInputMultiplier: .01,
addedLightInputMultiplier: .02,
cx: w / 2,
cy: h / 2,
repaintAlpha: .04,
hueChange: .1
},
tick = 0,
lines = [],
dieX = w / 2 / opts.len,
dieY = h / 2 / opts.len,
baseRad = Math.PI * 2 / 6;
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, w, h);
function loop() {
window.requestAnimationFrame(loop);
++tick;
ctx.globalCompositeOperation = 'source-over';
ctx.shadowBlur = 0;
ctx.fillStyle = 'rgba(0,0,0,alp)'.replace('alp', opts.repaintAlpha);
ctx.fillRect(0, 0, w, h);
ctx.globalCompositeOperation = 'lighter';
if (lines.length < opts.count && Math.random() < opts.spawnChance) lines.push(new Line);
lines.map(function (line) {
line.step();
});
}
function Line() {
this.reset();
}
Line.prototype.reset = function () {
this.x = 0;
this.y = 0;
this.addedX = 0;
this.addedY = 0;
this.rad = 0;
this.lightInputMultiplier = opts.baseLightInputMultiplier + opts.addedLightInputMultiplier * Math.random();
this.color = opts.color.replace('hue', tick * opts.hueChange);
this.cumulativeTime = 0;
this.beginPhase();
}
Line.prototype.beginPhase = function () {
this.x += this.addedX;
this.y += this.addedY;
this.time = 0;
this.targetTime = (opts.baseTime + opts.addedTime * Math.random()) | 0;
this.rad += baseRad * (Math.random() < .5 ? 1 : -1);
this.addedX = Math.cos(this.rad);
this.addedY = Math.sin(this.rad);
if (Math.random() < opts.dieChance || this.x > dieX || this.x < -dieX || this.y > dieY || this.y < -dieY) this.reset();
}
Line.prototype.step = function () {
++this.time;
++this.cumulativeTime;
if (this.time >= this.targetTime) this.beginPhase();
var prop = this.time / this.targetTime,
wave = Math.sin(prop * Math.PI / 2),
x = this.addedX * wave,
y = this.addedY * wave;
ctx.shadowBlur = prop * opts.shadowToTimePropMult;
ctx.fillStyle = ctx.shadowColor = this.color.replace('light', opts.baseLight + opts.addedLight * Math.sin(this.cumulativeTime * this.lightInputMultiplier));
ctx.fillRect(opts.cx + (this.x + x) * opts.len, opts.cy + (this.y + y) * opts.len, 2, 2);
if (Math.random() < opts.sparkChance) ctx.fillRect(opts.cx + (this.x + x) * opts.len + Math.random() * opts.sparkDist * (Math.random() < .5 ? 1 : -1) - opts.sparkSize / 2, opts.cy + (this.y + y) * opts.len + Math.random() * opts.sparkDist * (Math.random() < .5 ? 1 : -1) - opts.sparkSize / 2, opts.sparkSize, opts.sparkSize)
}
loop();
window.addEventListener('resize', function () {
w = c.width = window.innerWidth;
h = c.height = window.innerHeight;
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, w, h);
opts.cx = w / 2;
opts.cy = h / 2;
dieX = w / 2 / opts.len;
dieY = h / 2 / opts.len;
});
//# sourceURL=pen.js
Thanks a lot!
Original piece of code from: http://codepen.io/towc/pen/mJzOWJ
by Matei Copot
You can do this using an iframe and placing it as an absolute element with full body width and height like this:
HTML:
<body>
<div id="iframe"><iframe name="result" sandbox="allow-forms allow-popups allow-scripts allow-same-origin" frameborder="0" src="//fiddle.jshell.net/oleg_korol/a1bxr5ua/1/show/"></iframe></div>
<!--Your page content-->
</body>
CSS:
html, body {
margin:0px;
width:100%;
height:100%;
overflow:hidden;
}
iframe {
width:100%;
height:100%;
}
#iframe {
position: absolute;
float: left;
clear: both;
width: 100%;
height: 100%;
z-index: 0;
}
Here is a jsfiddle with above codes: https://jsfiddle.net/AndrewL32/kkLLxkxk/2/
And here is a StackOverflow snippet with above codes:
html, body {
margin:0px;
width:100%;
height:100%;
overflow:hidden;
}
iframe {
width:100%;
height:100%;
}
#iframe {
position: absolute;
float: left;
clear: both;
width: 100%;
height: 100%;
z-index: 0;
}
<div id="iframe"><iframe name="result" sandbox="allow-forms allow-popups allow-scripts allow-same-origin" frameborder="0" src="//fiddle.jshell.net/oleg_korol/a1bxr5ua/1/show/"></iframe></div>
WITHOUT IFRAME:
If you want to use the canvas as the background-image for the whole page, then the current code that you are using should work fine with width and height defined:
canvas {
position:absolute;
width:100%;
height:100%;
top:0px;
left:0px;
}
However if you want it as the background-image only for a certain div, then you can just add a position:relative; property to the parent div like this:
HTML:
<div id="canvas-box">
<canvas id=c></canvas>
</div>
CSS:
#canvas-box {
position:relative;
width:500px;
height:500px;
}
canvas {
position: absolute;
top: 0;
left: 0;
width:100%;
height:100%;
}
Here is a jsfiddle for adding canvas as background for a specific div: http://jsfiddle.net/AndrewL32/a1bxr5ua/5/