How to display image landscape - html

I have a website which targets mobile phones, if a user clicks on a 16:9 scaled responsive image, I want clicked image to be displayed landscape, so that the user can rotate his phone to view the image in full size. I can't save the image rotated because it is an external resource. Is there any way I can achieve the desired effect?
I can't simply rotate 90° because that would rotate the scaled image.
If I rotate the unscaled image, it extends the portrait viewport to landscape width and displays the rotated image centered.
I already tried using a canvas, but it didn't nearly fit my needs, the image gets destroyed by bad downscaling on Firefox using JSFiddle while it didn't display at all on the Intel XDK emulator.
Since my scenario doesn't seem that uncommon to me, I'm wondering whether I missed an easy solution.

Found a jsfiddle doing that, and made it simpler for you.
Check it out: http://jsfiddle.net/7fw66/39/
html:
<div>
<canvas id="canvas"><img id="image" src="http://3.bp.blogspot.com/-JhISDA9aj1Q/UTECr1GzirI/AAAAAAAAC2o/5qmvWZiCMRQ/s1600/Twitter.png" /></canvas>
</div>
javascript:
var screenwidth = 400;
var imgurl = "http://3.bp.blogspot.com/-JhISDA9aj1Q/UTECr1GzirI/AAAAAAAAC2o/5qmvWZiCMRQ/s1600/Twitter.png";
$(document).ready(function () {
loadImage();
$('#restore').click(function () {
loadImage();
});
$('#rotate_ccw').click(function () {
rotate_ccw();
});
$('#rotate_cw').click(function () {
rotate_cw();
});
});
function loadImage() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.setTransform(1, 0, 0, 1, 0, 0);
var img = new Image();
if (imgurl == null || imgurl == "") {
imgurl = defaultimgurl;
}
img.src = imgurl;
var maxsize = screenwidth;
var w = maxsize;
var ratio = (img.width / w);
var h = (img.height / ratio);
canvas.width = w;
canvas.height = h;
img.onload = function () {
ctx.drawImage(img, 0, 0, w, h);
};
ctx.save();
}
function rotate_cw() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.src = imgurl;
var maxsize = screenwidth;
var w = maxsize;
var ratio = (img.width / w);
var h = (img.height / ratio);
canvas.width = h;
canvas.height = w;
ctx.translate(w - h, w);
ctx.rotate((-90 * Math.PI) / 180);
ctx.translate(0, -(w - h));
ctx.drawImage(img, 0, 0, w, h);
ctx.save();
}
function rotate_ccw() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.src = imgurl;
var maxsize = screenwidth;
var w = maxsize;
var ratio = (img.width / w);
var h = (img.height / ratio);
canvas.width = h;
canvas.height = w;
ctx.translate(h, 0);
ctx.rotate((90 * Math.PI) / 180);
ctx.drawImage(img, 0, 0, w, h);
ctx.save();
}
function urlProvided() {
var userinput = document.getElementById('imageurl');
imgurl = userinput.value;
loadImage();
}

Related

HTML Canvas to WPF XAML Canvas

I have an ASP.NET application that allows users to click or tap on a Canvas to indicate pain locations on a body image. A body image is displayed on the Canvas and is the same size as the Canvas.
function drawBodyMap() {
var c = document.getElementById('myCanvas');
var ctx = c.getContext('2d');
var imageObj = new Image();
imageObj.src = 'https://.../body.jpg';
imageObj.onload = function () {
ctx.drawImage(imageObj, 0, 0, 600, 367);
};
}
<canvas id="myCanvas" width="600" height="367"></canvas>
<script>
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
canvas.addEventListener('mouseup', function (evt) {
if (ixPos > 9)
return;
var mousePos = getMousePos(canvas, evt);
bodyX[ixPos] = mousePos.x;
bodyY[ixPos] = mousePos.y;
painType[ixPos] = pain_type;
ixPos++;
ctx.beginPath();
ctx.arc(mousePos.x, mousePos.y, 8, 0, 2 * Math.PI);
if (pain_type == 1)
ctx.fillStyle = "#DC143C";
else if (pain_type == 2)
ctx.fillStyle = "#EA728A";
else if (pain_type == 3)
ctx.fillStyle = "#DAA520";
else if (pain_type == 4)
ctx.fillStyle = "#008000";
else if (pain_type == 5)
ctx.fillStyle = "#4169E1";
ctx.fill();
}, false);
</script>
The X,Y points added to the Canvas on the body image are saved to a database. These points are then loaded into a WPF application that displays the same body image on an XAML Canvas. C# code then adds the points over the image.
WPF CODE:
private void DisplayBodyPain()
{
List<BodyPain> pain = gFunc.sws.GetBodyPain(MemberID);
foreach (BodyPain bp in pain)
{
Border b = new Border();
b.Tag = bp.PainType.ToString();
b.Cursor = Cursors.Hand;
b.Width = 16;
b.Height = 16;
b.CornerRadius = new CornerRadius(8);
b.Background = GetPainBrush((byte)bp.PainType);
cvsBody.Children.Add(b);
Canvas.SetTop(b, bp.YPos);
Canvas.SetLeft(b, bp.XPos);
}
}
The problem I have is that the points drawn on the XAML Canvas are all slightly different from the points that were drawn on the HTML Canvas. Each point is not in exactly the same location.
Is there a way I can fix this? Should I be doing it differently?
HTML Canvas
WPF Canvas
I think you need to subtract the size of the marker from the coordinate where you want to place it. For the last two lines, try this instead:
Canvas.SetTop(b, bp.YPos - (b.Height / 2));
Canvas.SetLeft(b, bp.XPos - (b.Width / 2));
By subtracting half the marker's height and width, the center of the marker is placed on the desired coordinates.

Properties lost when copying HTML canvas or converting toDataURL

I'm using a native HTML 5 canvas to create a text effect then attempting to create an image from the canvas or copy the canvas to a fabric.js object, but the output doesn't reflect the changes done to the text.
Fiddle: https://jsfiddle.net/rf8kdxq1/2/
Something simple I hope?
var ctx = demo.getContext('2d'),
font = '64px impact',
w = demo.width,
h = demo.height,
curve,
offsetY,
bottom,
textHeight,
isTri = false,
dltY,
angleSteps = 180 / w,
i = w,
y,
os = document.createElement('canvas'),
octx = os.getContext('2d');
os.width = w;
os.height = h;
octx.font = font;
octx.textBaseline = 'top';
octx.textAlign = 'center';
curve = parseInt(110, 10);
offsetY = parseInt(4, 10);
textHeight = parseInt(64, 10);
bottom = parseInt(200, 10);
octx.fillText('BRIDGE', w * 0.5, 0);
/// slide and dice
i = w;
dltY = curve / textHeight;
y = 0;
while (i--) {
y = bottom - curve * Math.sin(i * angleSteps * Math.PI / 180);
ctx.drawImage(os, i, 0, 1, textHeight,
i, h * 0.5 - offsetY / textHeight * y, 1, y);
}
// ctx.drawImage(os, i, 0);
dataURL = os.toDataURL();
img = new Image();
img.src = dataURL;
img.onload = function() {
console.log(img);
};
var newCanv = new fabric.Canvas('canvasd');
function xfer() {
var image = new fabric.Image(os);
setTimeout(function() {
newCanv.add(image);
},500);
}
xfer();

Drag & drop image on canvas image

I want to drag & drop text above image. For that I am using canvas. I am using this code
<img id="scream" src="http://127.0.0.1/demo/images.jpg" alt="The Scream" style="display:none;" width="220" height="277"><p>Canvas:</p>
<canvas id="canvas" width="300" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
var c=document.getElementById("canvas");
var ctx1=c.getContext("2d");
var img=document.getElementById("scream");
ctx1.drawImage(img,10,10);
var canvas;
var ctx;
var x = 75;
var y = 50;
var dx = 5;
var dy = 3;
var WIDTH = 400;
var HEIGHT = 300;
var dragok = false,
text = "Hey there im moving!",
textLength = (text.length * 14)/2;
function rect(x,y,w,h) {
ctx.font = "14px Arial";
ctx.strokeText("Hey there im a moving!!", x, y);
}
function clear() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
}
function init() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
return setInterval(draw, 10);
}
function draw() {
clear();
ctx.fillStyle = "#FAF7F8";
ctx.fillStyle = "#444444";
rect(x - 15, y + 15, textLength, 30);
}
function myMove(e){
if (dragok){
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
}
}
function myDown(e){
if (e.pageX < x + textLength + canvas.offsetLeft && e.pageX > x - textLength + canvas.offsetLeft && e.pageY < y + 15 + canvas.offsetTop &&
e.pageY > y -15 + canvas.offsetTop){
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
dragok = true;
canvas.onmousemove = myMove;
}
}
function myUp(){
dragok = false;
canvas.onmousemove = null;
}
init();
canvas.onmousedown = myDown;
canvas.onmouseup = myUp;
I either able to show image or drag & drop text but I want both, please help me where I am wrong. You can check here:- http://jsfiddle.net/FWdSv/11/
When you're clearing the canvas, you're also clearing your image.
So the easy fix is to redraw the image in your draw function:
function draw() {
clear();
ctx.drawImage(img,0,0);
ctx.fillStyle = "#FAF7F8";
ctx.fillStyle = "#444444";
rect(x - 15, y + 15, textLength, 30);
}
Alternatively:
You could display your image underneath your canvas so it's not affected when you clear the canvas.

HTML5 canvas background image repeat

I have a html5 canvas that draws a sound wave. I have set the background as an background image, however, I want this background image to repeat. Can anyone tell me how I would do this and what I need to add into my code:
var backgroundImage = new Image();
backgroundImage.src = 'http://www.samskirrow.com/client-kyra/images/main-bg.jpg';
var canvas;
var context;
function init(c) {
canvas = document.getElementById(c);
context = canvas.getContext("2d");
soundManager.onready(function() {
initSound(clientID, playlistUrl);
});
aniloop();
}
function aniloop() {
requestAnimFrame(aniloop);
drawWave();
}
function drawWave() {
var step = 10;
var scale = 60;
// clear
context.drawImage(backgroundImage, 0, 0);
// left wave
context.beginPath();
context.moveTo(0, 256);
for ( var i = 0; i < 256; i++) {
context.lineTo(6 * i, 257 + waveLeft[i] * 80.);
}
context.lineWidth = 1;
context.strokeStyle = "#000";
context.stroke();
// right wave
context.beginPath();
context.moveTo(0, 256);
for ( var i = 0; i < 256; i++) {
context.lineTo(6 * i, 256 + waveRight[i] * 80.);
}
context.lineWidth = 1;
context.strokeStyle = "#000";
context.stroke();
}
function updateWave(sound) {
waveLeft = sound.waveformData.left;
}
return {
init : init
};
})();
You can see this code in action here:
http://www.samskirrow.com/client-kyra
Use the canvas' createPattern function
const canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
img = new Image();
img.src = 'https://www.google.nl/images/srpr/logo3w.png';
img.addEventListener('load', () => {
const ptrn = context.createPattern(img, 'repeat'); // Create a pattern with this image, and set it to "repeat".
context.fillStyle = ptrn;
context.fillRect(0, 0, canvas.width, canvas.height); // context.fillRect(x, y, width, height);
})
<canvas id="canvas" width="600px" height="600px"></canvas>
(This is the fastest of the 2 samples).
Or, try a manual implementation:
const canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
img = new Image();
img.src = 'https://www.google.nl/images/srpr/logo3w.png';
img.addEventListener('load', () => {
for (let w = 0; w < canvas.width; w += img.width) {
for (let h = 0; h < canvas.height; h += img.height) {
context.drawImage(img, w, h);
}
}
})
<canvas id="canvas" width="600px" height="600px"></canvas>

moving an image across a html canvas

I am trying to move an image from the right to the center and I am not sure if this is the best way.
var imgTag = null;
var x = 0;
var y = 0;
var id;
function doCanvas()
{
var canvas = document.getElementById('icanvas');
var ctx = canvas.getContext("2d");
var imgBkg = document.getElementById('imgBkg');
imgTag = document.getElementById('imgTag');
ctx.drawImage(imgBkg, 0, 0);
x = canvas.width;
y = 40;
id = setInterval(moveImg, 0.25);
}
function moveImg()
{
if(x <= 250)
clearInterval(id);
var canvas = document.getElementById('icanvas');
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
var imgBkg = document.getElementById('imgBkg');
ctx.drawImage(imgBkg, 0, 0);
ctx.drawImage(imgTag, x, y);
x = x - 1;
}
Any advice?
This question is 5 years old, but since we now have requestAnimationFrame() method, here's an approach for that using vanilla JavaScript:
var imgTag = new Image(),
canvas = document.getElementById('icanvas'),
ctx = canvas.getContext("2d"),
x = canvas.width,
y = 0;
imgTag.onload = animate;
imgTag.src = "http://i.stack.imgur.com/Rk0DW.png"; // load image
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // clear canvas
ctx.drawImage(imgTag, x, y); // draw image at current position
x -= 4;
if (x > 250) requestAnimationFrame(animate) // loop
}
<canvas id="icanvas" width=640 height=180></canvas>
drawImage() enables to define which part of the source image to draw on target canvas. I would suggest for each moveImg() calculate the previous image position, overwrite the previous image with that part of imgBkg, then draw the new image. Supposedly this will save some computing power.
Here's my answer.
var canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
var myImg = new Image();
var myImgPos = {
x: 250,
y: 125,
width: 50,
height: 25
}
function draw() {
myImg.onload = function() {
ctx.drawImage(myImg, myImgPos.x, myImgPos.y, myImgPos.width, myImgPos.height);
}
myImg.src = "https://mario.wiki.gallery/images/thumb/c/cc/NSMBUD_Mariojump.png/1200px-NSMBUD_Mariojump.png";
}
function moveMyImg() {
ctx.clearRect(myImgPos.x, myImgPos.y, myImgPos.x + myImgPos.width, myImgPos.y +
myImgPos.height);
myImgPos.x -= 5;
}
setInterval(draw, 50);
setInterval(moveMyImg, 50);
<canvas id="canvas" class="canvas" width="250" height="150"></canvas>
For lag free animations,i generally use kinetic.js.
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var hexagon = new Kinetic.RegularPolygon({
x: stage.width()/2,
y: stage.height()/2,
sides: 6,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4
});
layer.add(hexagon);
stage.add(layer);
var amplitude = 150;
var period = 2000;
// in ms
var centerX = stage.width()/2;
var anim = new Kinetic.Animation(function(frame) {
hexagon.setX(amplitude * Math.sin(frame.time * 2 * Math.PI / period) + centerX);
}, layer);
anim.start();
Here's the example,if you wanna take a look.
http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-animate-position-tutorial/
Why i suggest this is because,setInterval or setTimeout a particular function causes issues when large amount of simultaneous animations take place,but kinetic.Animation deals with framerates more intelligently.
Explaining window.requestAnimationFrame() with an example
In the following snippet I'm using an image for the piece that is going to be animated.
I'll be honest... window.requestAnimationFrame() wasn't easy for me to understand, that is why I coded it as clear and intuitive as possible. So that you may struggle less than I did to get my head around it.
const
canvas = document.getElementById('root'),
btn = document.getElementById('btn'),
ctx = canvas.getContext('2d'),
brickImage = new Image(),
piece = {image: brickImage, x:400, y:70, width:70};
brickImage.src = "https://i.stack.imgur.com/YreH6.png";
// When btn is clicked execute start()
btn.addEventListener('click', start)
function start(){
btn.value = 'animation started'
// Start gameLoop()
brickImage.onload = window.requestAnimationFrame(gameLoop)
}
function gameLoop(){
// Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height)
// Draw at coordinates x and y
ctx.drawImage(piece.image, piece.x, piece.y)
let pieceLeftSidePos = piece.x;
let middlePos = canvas.width/2 - piece.width/2;
// Brick stops when it gets to the middle of the canvas
if(pieceLeftSidePos > middlePos) piece.x -= 2;
window.requestAnimationFrame(gameLoop) // Needed to keep looping
}
<input id="btn" type="button" value="start" />
<p>
<canvas id="root" width="400" style="border:1px solid grey">
A key point
Inside the start() function we have:
brickImage.onload = window.requestAnimationFrame(gameLoop);
This could also be written like: window.requestAnimationFrame(gameLoop);
and it would probably work, but I'm adding the brickImage.onload to make sure that the image has loaded first. If not it could cause some issues.
Note: window.requestAnimationFrame() usually loops at 60 times per second.