I am doing drag and drop and want to use a different drag image than the default. But I would also like to scale the size of the drag image depending on the size of the element where the drag starts. I have tried doing the following:
<div id="drag-with-image" draggable="true">drag me</div>
<script>
document.getElementById("drag-with-image").addEventListener("dragstart", function(e) {
var img = document.createElement("img");
img.src = "https://www.w3schools.com/css/paris.jpg";
img.style.width = "60px";
img.style.height = "40px";
e.dataTransfer.setDragImage(img, 0, 0);
}, false);
</script>
But the drag image is always displayed as full size.
Is there any way the drag image size can be scaled dynamically?
Yes, it is possible to scale a custom drag image.
The Problem
If you're using setDragImage with an image element, what will be drawn is the image in its intrinsic size (content size before any modification). This means that setting the image size doesn't help. However, as mentioned in MDN Docs, you can also set a drag image to be something else:
If Element is an img element, then set the drag data store bitmap to the element's image (at its intrinsic size); otherwise, set the drag data store bitmap to an image generated from the given element (the exact mechanism for doing so is not currently specified).
Furthermore, it also mentions that the "other elements" can be any visible element or even a <canvas>:
However, if a custom image is desired, the DataTransfer.setDragImage() method can be used to set the custom image to be used. The image will typically be an element but it can also be a or any other visible element.
Solution
To draw an image that is smaller than its intrinsic size and setting it to drag image, you can:
Load the image to an image element
Create a canvas to be drawn with the image
When drawing to the canvas, adjust the width and height of the drawn image accordingly
Here's a working example.
document.getElementById('drag-with-image').addEventListener('dragstart', function(e) {
var img = document.createElement('img')
var canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d')
// Setting img src
img.src = 'https://www.w3schools.com/css/paris.jpg'
// Drawing to canvas with a smaller size
canvas.width = img.width * 0.1
canvas.height = img.height * 0.1
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
// Setting drag image with drawn canvas image
e.dataTransfer.setDragImage(canvas, 0, 0)
}, false)
<div id="drag-with-image" draggable="true">drag me</div>
Related
Click here to view image
Step1) I am drawing an image of 1920*1080 to canvas1 with the drawImage(image,0,0);
setp2) Now i am taking another logo image and drawing it to another canvas called canvas2 with the drawImage(logo,0,0);
I used fabricjs to for logo drag able and re sizable functionalities.
Step3) Then i am drawing canvas1 & canvas2 to another canvas called canvas3 and downloading it.
In this case everything is fine except image is displaying large(1920*1080). for user experience I have used image resize method to reduce the image and displayed in 900*500 canvas. But when i am downloding i should get the original canvas of 1920*1080 with logo. But i am getting 900*500 with logo.
Can any one help in this regards will be greatful
The resizing code
Here real width & real Height are width & height of background image
function ImageResize(){
var d_canvas = document.getElementById('canvas');
var context = d_canvas.getContext('2d');
var background = document.getElementById('background');
var wrh = realWidth / realHeight;
newWidth = d_canvas.width;
newHeight = newWidth / wrh;
if (newHeight > d_canvas.height) {
newHeight = d_canvas.height;
newWidth = newHeight * wrh;
}
context.drawImage(background,0,0, newWidth , newHeight);
}
Use the extended form of drawImage to scale and reposition the logo over the original background image:
Create a 3rd html5 canvas sized to 1920x1080 and draw your step1-image to the 3rd canvas.
Recalculate the Logo coordinates & sizes provided by FabricJS from 900x500 to 1920x1080:
// pseudo-code
// Given FabricJS's position & size of the logo on a 950x500 stage
// Calc the logo's relative position & size vs a larger background
logoX *= 1920/900;
logoY *= 1080/500;
logoWidth *= 1920/900;
logoHeight *= 1080/500;
Draw the logo onto the 3rd canvas using the recalculated position & size
thirdContext.drawImage(
logoImage,
0,0,logoImage.width,logoImage.height,
logoX,logoY,logoWidth,logoHeight
);
Export the 3rd canvas
I'm drawing a image to a canvas, and when doing so the image gets downscaled to the canvas(which makes it lose quality) even though the image is the same size as the canvas, thats because the img does a good job scaling down the actual img that in reality has a bigger naturalheight and naturalwidth. I know there is possible ways to make this quality better, however i have no need of actually showing this canvas to the user/no need of downscaling. Therefore am i wondering if there is any way to drawImage that is bigger than the screen and hold it somewhere? Heard someone mention a box object or a camera object somewhere but couldn't really get use of that information only.
Question, is it possible to draw a canvas bigger than the screen? in that case how?
This is the code im working with atm
var image = document.getElementById('insertedImg');
var height = $("#insertedImg").height();
var width = $("#insertedImg").width();
var c=document.getElementById("canvass");
var ctx=c.getContext("2d");
c.height=height;
c.width=width;
ctx.drawImage(image,0,0,width,height);
Use an offscreen canvas, you just need to create a new canvas and set its height and width accordingly. Then you can append it to an element or export the image as a base64 string or whatever you need.
//canvas is not visible unless appended to a DOM element
var canvas = document.createElement('canvas');
canvas.width = $("#insertedImg").height();
canvas.height = $("#insertedImg").width();
var ctx = canvas.getContext('2d');
//do the drawing, etc.
ctx.drawImage(...);
//export the image
var img = canvas.toDataURL("image/png");
I have a canvas object that I want to put an image in for a web application. I can get the image loaded, but I've run into 2 problems: The image won't stretch to the canvas, and the canvas won't stretch to cover the entire div in any browser but Firefox.
http://jsfiddle.net/LFJ59/1/
var canvas = $("#imageView");
var context = canvas.get(0).getContext("2d");
$(document).ready(drawImage());
$(window).resize(refreshCanvas());
refreshCanvas();
function refreshCanvas() {
//canvas/context resize
canvas.attr("width", $(window).get(0).innerWidth / 2);
canvas.attr("height", $(window).get(0).innerHeight / 2);
drawImage();
};
function drawImage() {
//shadow
context.shadowBlur = 20;
context.shadowColor = "rgb(0,0,0)";
//image
var image = new Image();
image.src = "http://www.netstate.com/states/maps/images/ca_outline.gif";
$(image).load(function () {
image.height = canvas.height();
image.width = canvas.width();
context.drawImage(image);
});
};
Is there a solution to making the canvas responsive? Or do I just need to lock the canvas and image down to predefined sizes?
width and height of image are read-only so that won't work.
Try instead:
context.drawImage(image, 0, 0, canvas.width, canvas.height);
This will draw the image the same dimension as the canvas is (you don't need to reload the image every time btw. - just load it once globally and reuse the image variable.)
<canvas id="imageView" width="1000" height="1000" style="width:100%; height:100%"></canvas>
Both CSS and height and width attributes can be used and do not need to agree in size. The CSS style will determine the displayed size, you asked for a canvas that can stretch. The width and height control the number of pixels the canvas uses for drawing.
for example this will be scaled 10 to 1, and with anti-aliasing scrolling an drawing in this canvas would be as smooth as silk.
<canvas id="imageView" width="1000" height="1000" style="width:100px; height:100px"></canvas>
If CSS is not used, their defaults will be the width and height attributes of the canvas element.
I am working on a site where the body has many color. When the content is scrolled down the background of the content changes.
In the below image u can see body text with blue color background. So when the content is scrolled down with the scrollbar then the background image should also scroll along with the content.
So what happens is when scroll bar stops at a color like blue then automatically the menu header(Home) background should change to blue.
First of all we should know what we want to do. Step one is actually get a color of the image, thus acces a property of the image.
However the browser cannot get direct information of the image itself(You can, of course, get information from the element of the image). However one webbrowser drawing method let us control every aspect of a image: Canvas.
So first we have to convert our image to an canvas element.
This is fairly simply done with drawImage(img, posx, posy, canvasWidth, canvasHeight);
We will also stretch the canvas image + the element to the entire screen. The reason we want to define to size also at the canvas is because this way the canvas will calculate every new generated pixel, so we can acces every of the new pixels:
var screenWidth = window.innerWidth,
screenHeight = window.innerHeight,
c = document.createElement('canvas');
ctx = c.getContext("2d"),
img = document.getElementById("image");
c.width = screenWidth;
c.height = screenHeight;
ctx.drawImage(img, 0, 0, screenWidth, screenHeight);
$(c).attr('id', 'c');
$('body').prepend(c);
$(img).remove();
An Canvas element as is dynamically made and will fit to the screen size(Note that this is only at first start of the webbrowser. So when you resize the canvas will not resize with the screen).
We remove the image as it is no use anymore. It's a good practive to transform from image to canvas in my opinion. As you will be certain that the image will be loaded in the browser first and then transformed to a canvas element.
Next we're going to acces a pixel. You can acces pixel data with getImageData(offsetX, offsetY, sizeX, sizeY).data; And RGBA color array will be returned.
Now the offsetX and offsetY will be the offset of the element color picker. Note that this elements offset should be relative to the webbrowsers viewport as the background is fixed You can do this with getBoundingClientRect();
The size is just 1x1 as we want 1 pixel.
This all should happen when the user is scrolling, you can catch the scroll event with .scroll(function); :
$(window).scroll(function () {
var offset = document.getElementById('color').getBoundingClientRect(),
offsetX = offset.left,
offsetY = offset.top;
var color = document.getElementById('c').getContext('2d').getImageData(offsetX, offsetY, 1, 1).data;
$('header').css('background-color',"rgba("+ color[0] + ', ' + color[1] + ', '+ color[2] + ', ' + color[3] + ")");
});
Where we add the rgba array colors just with the first 4 indexes(Because and rgba collor pattern never has more as 4 values) with plain css to the header element.
Loading External image into a canvas
When you want to transform an external image to a canvas element you might get this error:
Cross-origin image load denied by Cross-Origin Resource Sharing policy.
It is for security reasons that you can't fully acces this image.
As explained here: HTML 5 canvas getImageData from an externally-loaded image
There are some external hosts that supports this, for example dropbox.
Local
However when you just store it locally it will just work fine.
jsFiddle
This method was tested in chrome, IE and firefox.
I want to use those external (dropbox) files
I'm not sure why this happens but for some reason with this method there are still some security diffecults. To enable this CORS you have to add a image property .crossOrigin = "Anonymous";. However when you load the image with HTML the the element has been made without this property. So you should assign this property when the image is created:
var canvas = document.getElementById("c"),
ctx = canvas.getContext("2d"),
screenWidth = window.innerWidth,
screenHeight = window.innerHeight;
// Using image WITH crossOrigin=anonymous
// Succeeds in Chrome+Mozilla, Still fails in IE
var externalImage2 = new Image();
externalImage2.onload = function(){
canvas.width= screenWidth;
canvas.height= screenHeight;
ctx.drawImage(externalImage2, 0, 0, screenWidth, screenHeight);
// this will FAIL on a CORS violation
}
externalImage2.crossOrigin = "Anonymous";
externalImage2.src="https://dl.dropboxusercontent.com/s/8g8lgmdx341j1d6/rainbow_gradient_horizontal.jpg";
This is just an picture i uploaded to my dropbox where i just shared the photo. Note:
The way to convert a share link to a direct link is to change the domain from "www.dropbox.com" to "dl.dropboxusercontent.com". See https://www.dropbox.com/developers/blog/53/programmatically-download-content-from-share-links.
source: Cross-origin image load from cross-enabled site is denied
This creates an image and puts it into an excisting canvas element. So note that you should have a canvas element into your HTML.
jsFiddle
This method does only work for chrome and firefox as other browsers still have some security issues.
Additional note is the pixel that gets captured is the top-left pixel of the 'color-pick' element. You can adjust this offset if you want it to catch, for example, the middle pixel of the element.
This was a very interesting question. I hope it helped!
well, you may give background color of the home bar as transparent if you have no band between the home and the content.
.home{
background:transparent;
}
I'm dynamically drawing a floorplan through canvas which you can scroll through up/down left/right but I would like to save the whole image of the floorplan for other uses. I know I can scale the floorplan down and capture the image but I need it to be in a higher resolution than the actual screen I'm capturing it on.
I'm currently using FileSaver.js to save the canvas as a bitmap because it's super easy.
Is this possible?
It's hard to tell without more information, but you can create a larger canvas (of the size you need it to be) and let it hidden. Then when you want to capture, you re-draw everything into that canvas and save your picture from it instead of the one that is displayed.
So you don't need to save the canvas, but the image.
I don't know your FileSaver.js, but if it cannot save an image directly,
putting the image inside a new canvas is easy :
function getCanvasFromImage(img) {
var cv = document.createElement('canvas');
cv.width = img.width; cv.height = img.height;
cv.getContext('2d').putImage(img, 0, 0);
return cv;
}