I see that there are ways to do this in webkit browsers, but I don't see ways to do it in others. Is this simply a feature that hasn't been implemented in all the browsers?
I don't have standard images, so clip won't work. I may have to render everything ahead of time, which will make my work exponential, but you deal with what you have, right?
I'd also want to be able to activate this stuff from javascript. :/
Thanks if you can provide support.
Just off the top of my head - and without an actual problem from you for us to solve - here's a possible way to accomplish what you want...
HTML
<div class="myImage">
<img src="path_to_image" title="Lorem ipsum" alt="Dolar sit amet" />
<div class="myMask">
</div><!-- /myMask -->
</div><!-- /myImage -->
CSS
.myImage {
position: relative;
}
.myMask {
position:absolute;
top: 0;
left: 0;
background-color: transparent;
background-image: url('path_to_masking_image');
}
Alternatively, use an <img /> inside the myMask div, and remove the background-image property from the CSS.
The way it's currently laid out, you would need two images: the image itself in all its glory, and the mask.
The way you would accomplish the 'masking effect' is to have the mask image be a static solid color that matches background of the container its in - ie white, black, whatever.
Kapeesh? This would work in all browsers, which is what you asked for. The background-clip property has -webkit and -moz selectors, but is not supported in browsers like IE or (to my knowledge) Opera.
Here are my 2 cents, if it is indeed CSS Sprites you are after.
<head>
<style type="text/css"><!--
#imagemask {
background-image: url(image.png);
background-repeat: no-repeat;
background-color: transparent;
height: 40px;
width: 40px;
}
.mask1 { background-position: top left; }
.mask2 { background-position: 0 40px; }
.mask3 { background-position: 0 80px; }/* And so on, however your image file is 'layed out' */
--></style>
<script type="text/javascript">
function mask1(){ document.getElementById("imagemask").setAttribute("class", "mask1"); }
function mask2(){ document.getElementById("imagemask").setAttribute("class", "mask1"); }
function mask3(){ document.getElementById("imagemask").setAttribute("class", "mask1"); }
</script>
</head>
<body>
mask 1
mask 2
mask 3
<div id="imagemask" class="mask1"></div>
</body>
We define the div#imagemask to contain 1 image file as a background and set it to not repeat around, as that would sort of defy the point.
We define how to "move around" the image inside the "mask" (div) with fixed width and height.
As a reference, I've then added the javascript you need to switch between the masks on the fly. I wrote that in about 10 seconds, you could probably write something a little more elegant if you want.
Add the links with onclick= events
Finally, add the div#imagemask to the body.
Given that I don't know the width or height of your image file or it's target masking, you'll have to do some substantial edits to this code. But you get the idea :)
I'm just going to skip the CSS variant in favor of this:
Example of a working mask: http://gumonshoe.net/NewCard/MaskTest.html
I acquired a javascript class from another website tutorial:
http://gumonshoe.net/js/canvasMask.js
It reads the image data and applies the alpha pixels from the mask to the target image:
function applyCanvasMask(image, mask, width, height, asBase64) {
// check we have Canvas, and return the unmasked image if not
if (!document.createElement('canvas').getContext) return image;
var bufferCanvas = document.createElement('canvas'),
buffer = bufferCanvas.getContext('2d'),
outputCanvas = document.createElement('canvas'),
output = outputCanvas.getContext('2d'),
contents = null,
imageData = null,
alphaData = null;
// set sizes to ensure all pixels are drawn to Canvas
bufferCanvas.width = width;
bufferCanvas.height = height * 2;
outputCanvas.width = width;
outputCanvas.height = height;
// draw the base image
buffer.drawImage(image, 0, 0);
// draw the mask directly below
buffer.drawImage(mask, 0, height);
// grab the pixel data for base image
contents = buffer.getImageData(0, 0, width, height);
// store pixel data array seperately so we can manipulate
imageData = contents.data;
// store mask data
alphaData = buffer.getImageData(0, height, width, height).data;
// loop through alpha mask and apply alpha values to base image
for (var i = 3, len = imageData.length; i < len; i = i + 4) {
imageData[i] = alphaData[i];
}
// return the pixel data with alpha values applied
if (asBase64) {
output.clearRect(0, 0, width, height);
output.putImageData(contents, 0, 0);
return outputCanvas.toDataURL();
}
else {
return contents;
}
}
Related
I am creating a discolor function for designing a jeans pant. I have 2 images of equal sizes one with dark color and other with lighter color. What I want to do is if someone draw a line with brush on my canvas it need to copy same area from a hidden image and need to fill that line with pasting that area from hidden image.
See these images to understand my requirement
Image 1 which showing over canvas.
Image 2 is hidden Image. It must not show on any condition
Image 3 is requirement.
(source: hhcnct.com)
(source: hhcnct.com)
Like you can see in image 2 top area is not lighter it means if someone brush on top no differnce will occur as both have same color at top.
Should I need to create a hidden layer first from second image?
I am looking a solution in fabric.js because my current base setup in fabric.js.
Anybody can help please?
JSFIDDLE Link
https://jsfiddle.net/19kpdwjx/
Need to finish the answer. Had no idea how to save a draft.
Answere incomplete here
var canvas = new fabric.Canvas('canvas-front', {
preserveObjectStacking: true,
controlsAboveOverlay: true
});
canvas.backgroundColor = '#ebeced';
window.fabric.Image.fromURL('https://evolveapothecary.com/frontnew.jpg', (img) => {
canvas.freeDrawingBrush.color = new fabric.Pattern({ source: img._element, repeat: 'no-repeat' });
});
window.fabric.Image.fromURL('https://evolveapothecary.com/frontnew.jpg', (img) => {
img.set({
left: 0,
top: 0
});
canvas.add(img);
})
canvas.renderAll();
canvas.isDrawingMode = true;
canvas.freeDrawingBrush.width = 20;
[hidden] {
display: none!important;
}
.painting-area{
overflow: hidden;
margin: 0;
height: auto;
border: 1px solid #e0e0e0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.min.js"></script>
<div class="painting-area">
<canvas id="canvas-front" width="680" height="680"></canvas>
</div>
I am using draw2dtouch 6.1.66 version (latest version). Initially width and height of canvas was 1000px and 800px respectively. On button click, I am changing the canvas width and height to 2170px and 902px respectively.
Now I cannot drag rectangle figure beyond 1000px width-wise. It gets stuck to 1000px which was initial width.
Note: I check my html, both canvas div and svg shows width:2170px and height:902px.
<div _ngcontent-awi-17="" draw2d-canvas="" id="canvas" style="height: 902px; cursor: default; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); width: 2170px;">
<svg height="902" version="1.1" width="2170" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="overflow: hidden; position: absolute; left: -0.828125px;">
Here is my code:
$("#canvas").css("height",902);
$("#canvas").css("width", 2170);
canvas.setDimension(new draw2d.geo.Rectangle(0, 0, 2170, 902));
It may be and old post, but I had the same issue using same version, and my solution might be useful for some other people coming back.
It seems when the canvas is created Canvas.regionDragDropConstraint is initialized with the original size of the canvas, restrincting the area in which objects can be dragged inside. I had to modify the method Canvas.setDimension, and added the update of the attribute, so when resized, it's updated in all the figures referencing the same object.
/**
* #method
* Tells the canvas to resize. If you do not specific any parameters
* the canvas will attempt to determine the height and width by the enclosing bounding box
* of all elements and set the dimension accordingly. If you would like to set the dimension
* explicitly pass in an draw2d.geo.Rectangle or an object with <b>height</b> and <b>width</b> properties.
*
* #since 4.4.0
* #param {draw2d.geo.Rectangle} [dim] the dimension to set or null for autodetect
*/
setDimension: function(dim, height)
{
if (typeof dim === "undefined"){
var widths = this.getFigures().clone().map(function(f){ return f.getAbsoluteX()+f.getWidth();});
var heights = this.getFigures().clone().map(function(f){ return f.getAbsoluteY()+f.getHeight();});
this.initialHeight = Math.max.apply(Math,heights.asArray());
this.initialWidth = Math.max.apply(Math,widths.asArray());
}
else if(dim instanceof draw2d.geo.Rectangle){
this.initialWidth = dim.w;
this.initialHeight = dim.h;
}
else if(typeof dim.width ==="number" && typeof dim.height ==="number"){
this.initialWidth = dim.width;
this.initialHeight = dim.height;
}
else if(typeof dim ==="number" && typeof height ==="number"){
this.initialWidth = dim;
this.initialHeight = height;
}
this.html.css({"width":this.initialWidth+"px", "height":this.initialHeight+"px"});
this.paper.setSize(this.initialWidth, this.initialHeight);
this.setZoom(this.zoomFactor, false);
// MODIFICATION START TO CORRECT DRAG AND DROP PROBLEM
// Add modification to the Region Drap and Drop Policy, so it does not restricts objects movements on resize.
this.regionDragDropConstraint.constRect.w = this.getWidth();
this.regionDragDropConstraint.constRect.h = this.getHeight();
// MODIFICATION END
return this;
}
Setting the width and height of a canvas using css, will result in scale like effect, because the underlying imageData array is not updated to the new dimensions.
So if you need to scale your canvas, use the attributes of the canvas, like so:
$('#canvas').attr({width: <width>, height: <height>});
Keep in mind that changing those values will clear the canvas and you need to redraw everything.
I'm making a website for my art gallery. Part of what I need to do is display images to the viewers in a way in which they can view them. And I want to do this without reducing the quality of the images, or having to save all of my images in many different sizes to cater to every user.
So, I've made a Javascript function to resize my images to fit completely on the viewer's screen. My code looks like
<img src="[image.png]" onload="setGoodHeight(this);">
where the function setGoodHeight(element) is defined as:
function setGoodHeight (element) {
if(window.innerHeight-50 < element.height) {
var h = element.height;
var w = element.width;
element.height = window.innerHeight - 50;
element.width = w * element.height / h;
}
if (window.innerWidth-100 < element.width) {
var h = element.height;
var w = element.width;
element.width = window.innerWidth - 100;
element.height = h * element.width / w;
}
}
In shorthand, this first checks whether the image is higher than the screen it's trying to be displayed on, and if it is (it usually is) the image is resized to fit comfortably on the screen. Then it checks if, after this, the image is wider than the screen, and if so it shrinks it further. I have verified that this code works.
However, the image is contained within a class called .post I want the post area to wrap to that of the image, at least in width, and so at the end of my javascript function, I added this code:
element.parentNode.width = element.width + 40;
But the post doesn't resize itself. For reference, the code on the actual webpage concerning this can be boiled down to
<div class="post">
<img src="[image.jpg]" onload="setGoodHeight(this);">
</div>
and if you need to look around it a little more it can be found at this link.
How about a pure CSS solution, it will also update magically if the user resizes their browser.
html, body, #fullscreen {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#fullscreen {
background: url('http://www.nathanrouse.org/wp-content/uploads/2014/01/CrashTestDummy.jpg') center center no-repeat;
background-size: cover;
}
<div id="fullscreen"></div>
Check the doc for background-size. There are other values like "contain" that might suit you better.
I think you're looking for
item.naturalHeight
item.naturalWidth
I was using these in a function to set the max-height & max-width
function imageLoad(item) {
$(item).attr("max-height", item.naturalHeight);
$(item).attr("max-width", item.naturalWidth);
}
I'm working on an HTML5 browser game that can be divided into 3 parts: two UI panels on the left and right of a center set of square canvases for the playing surface. The three panels need to be horizontally aligned, and the total game needs to keep an aspect ratio of 16:9. The left and right panels should be of equal widths, and all three panels must be of equal height. I have specified a minimum width and height inside a resize() function called when an onresize event is detected.
Currently, each panel is a div, and all three are contained inside a section. Right now, the section isn't necessary, but I want to keep the game separated from extra content at the bottom of the screen that I might choose to add later.
The CSS style is as follows:
* {
vertical-align: baseline;
font-weight: inherit;
font-family: inherit;
font-style: inherit;
font-size: 100%;
border: 0 none;
outline: 0;
padding: 0;
margin: 0;
}
#gameSection {
white-space: nowrap;
overflow-x: hide;
overflow-y: hide;
}
#leftPanel, #centerPanel, #rightPanel {
display: inline-block;
}
#leftPanel {
background-color: #6495ed;
}
#centerPanel {
background-color: #e0ffff;
}
#rightPanel {
background-color: #b0c4de;
Right now, I have set the background color of each div just to show me when I'm correctly setting the size of each div.
The body of my HTML document is as follows:
<body onresize="resize()">
<section id="gameSection">
<div id="leftPanel">Left Panel.</div>
<div id="centerPanel">Center Panel.</div>
<div id="rightPanel">Right Panel.</div>
</section>
</body>
And finally, my resize() function (I created a separate function for resizing the game in case I add more elements below later):
function resize() {
var MIN_GAME_WIDTH = 800;
var MIN_GAME_HEIGHT = 450;
var GAME_ASPECT_RATIO = 16 / 9;
var width = window.innerWidth;
var height = window.innerHeight;
var gWidth, gHeight;
if(width < MIN_GAME_WIDTH || height < MIN_GAME_HEIGHT) {
gWidth = MIN_GAME_WIDTH;
gHeight = MIN_GAME_HEIGHT;
}
else if ((width / height) > GAME_ASPECT_RATIO) {
<!-- width is too large for height -->
gHeight = height;
gWidth = height * GAME_ASPECT_RATIO;
}
else {
<!-- height is too large for width -->
gWidth = width;
gHeight = width / GAME_ASPECT_RATIO;
}
resizeGame(gWidth, gHeight, GAME_ASPECT_RATIO);
}
function resizeGame(var gWidth, var gHeight, var aspectRatio) {
var gSection = document.getElementById("gameSection");
var lPanel = document.getElementById("leftPanel");
var cPanel = document.getElementById("centerPanel");
var rPanel = document.getElementById("rightPanel");
gSection.height = gHeight;
gSection.width = gWidth;
<!-- should the below be taken care of in the CSS? -->
lPanel.height = gHeight;
cPanel.height = gHeight;
rPanel.height = gHeight;
cPanel.width = cPanel.height;
lPanel.width = (gWidth - cPanel.width) / 2;
rPanel.width = lPanel.width;
}
I've tried a number of different commands to resize the divs, but it just isn't working for me. When I try adding test canvases, color appears, but the boxes still aren't the correct size. I have also considered loading an invisible background image to each div and scaling it to the desired size; however, I was able to resize my canvas using the above method before and it seemed to work just fine.
Additional Notes
While I've already had pretty good success resizing a single canvas, I don't want to use just one canvas for the game because not all parts of the UI need to be drawn at the same time.
I'm trying to keep this solely in Javascript.
I suspect that I could just use CSS to handle resizing by fixing the aspect ratio to 16:9 and using width:56.25% for the center panel and width:21.875% for the side panels, but that limits me to one aspect ratio and doesn't explain why my above script isn't working.
I can provide the entire HTML file if needed. This is what it's supposed to look like:
End Goal (without right panel)
Thank you!
UDPATE:
jsfiddle
I got it kind of working here. I made a lot of changes/minor fixes to the code before finding what was wrong (other than various syntax errors):
You were using .width and .height instead of .style.width and .style.height, and you were applying integers to these instead of strings with "px" appended to them. Both of these things are completely understandable to miss.
I also moved the onresize from the body tag into the JS, don't know why it wasn't working on jsfiddle, but this is good practice anyways.
In the future: learn how to debug JS using the console and when you ask questions, use small examples, not your entire codebase. This question could have been simplified to "How do I resize a div?" with one line of JS and one div. You also should consider not doing this specific thing in JS, and using flexbox as redbmk said.
I am tracing a point in an HTML5 video using canvas overlay. The canvas is on top of the video tag with the following style:
#my-canvas { width: 100%; height: 100%; position:absolute !important; z-index:100000; margin: 0 auto; background-color:rgba(68, 170, 213, 0.0); }
The points were captured via separate (Android) app. Here's how I plot the points on the canvas:
MyClass.prototype.drawLine = function(_context, _ctr, _color) {
_context.lineWidth = 2;
_context.lineJoin = 'round';
_context.strokeStyle = _color;
_context.moveTo(this.data["xs"][_ctr]*this.xOffset, this.data["ys"][_ctr]*this.yOffset);
_context.lineTo(this.data["xs"][_ctr+1]*this.xOffset, this.data["ys"][_ctr+1]*this.yOffset);
_context.stroke();
_context.closePath();
}
I multiply the data points with an offset value to compensate for the screen size. This is how I calculate the offset:
MyClass.prototype.calculateOffsets = function() {
this.yOffset = this.video.offsetHeight/parseFloat(this.data["height"]);
this.xOffset = this.video.offsetWidth/parseFloat(this.data["width"]);
}
This code works fine in a landscape video but not in portrait. I might be missing something with the offset calculation. I would appreciate if you can point me to the proper direction.
Thanks in advance.
When you set canvas size using CSS your canvas will actually always be 300x150 pixels. What you draw to it will be relative to that size.
Try instead to remove the 100% width and height from the CSS rule and set the canvas size for its bitmap every time you get an onresize event etc. CSS sets the element size; this will set the bitmap size (element will follow if no CSS is overriding):
_context.canvas.width = window.innerWidth;
_context.canvas.height = window.innerHeight;
and
#my-canvas {width: 100%; height: 100%;position:absolute...
Notice though that changing the canvas size will also clear it so you will have to redraw everything up to that point if that is needed.