I am using jquery mobile and I want to stop images from being resized larger than their actual dimensions, but still allow resizing if smaller particularly when displaying on desktop
I have rolled my own code below which works ok(ish) but I currently have 2 issues
when the image is resized beyond its actual size I get screen flicker as the image is displayed but the code kicks in and redisplays it to a smaller size
it doesn't always resize when double clicking the browser title bar
Can anyone help/advise on this please?
<img id="imgs" style="width:90%;" src="images/mypic.jpg" />
$(document).on('pageshow', '#index', function (event) {
resizeimage(awidth, aheight)
});
$(window).resize(function () {
resizeimage(awidth, aheight)
});
function resizeimage(maxwidth, maxheight) {
var width = $(imgs).width(); // Current image width
var height = $(imgs).height(); // Current image height
// **** this is trace output only
//$(windowwidth).text($(window).width());
//$(windowheight).text($(window).height());
//$(iwidth).text($(imgs).width());
//$(iheight).text($(imgs).height());
if (parseInt(width, 10) > maxwidth) {
//$(info).text('bigger'); // trace output
$(imgs).css("width", maxwidth); // dont allow image to resize larger than its actual size
} else {
//$(info).text('smaller'); // trace output
$(imgs).css("width", "100%"); // allow image to resize below its actual size
}
}
Related
Still very much a newbie to coding, so please be gentle :)
I'm hoping someone might be able to help how to use Paper.js on a second canvas after the first one has been executed?
I'm trying to use x2 canvas elements:
Canvas 1 - to capture a html5 video image still and convert to base64 (tick :-) = done)
Canvas 2 - Use the base64 image and perform the 'Working with Rasters to find the colors of pixels' and convert to circle paths (boo = fail :-( )
Something like this:
The code:
<script src="https://cdn.jsdelivr.net/npm/hls.js#latest"></script>
<video id="video" preload="auto" muted="" playsinline="" width="580" src="blob:https://www.georgefisher.co.uk/78e3a45c-ae07-4ea5-af56-45a5ed9cf1b0"></video>
<script>
var video = document.getElementById('video');
var videoSrc = 'https://camsecure.co/HLS/georgefisher.m3u8';
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(videoSrc);
hls.attachMedia(video);
}
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = videoSrc;
}
video.play()
</script>
<br>
<button onclick="capture()">Capture</button>
<br>
<canvas id="canvas" style="overflow:auto">
</canvas>
<canvas id="canvas2" resize>
<img src="" id="myImg"/></canvas>
var resultb64="";
function capture() {
var canvas = document.getElementById('canvas');
var video = document.getElementById('video');
canvas.width = video.videoWidth/4;
canvas.height = video.videoHeight/4;
canvas.getContext('2d').drawImage(video, 0, 0, video.videoWidth/4, video.videoHeight/4);
resultb64=canvas.toDataURL();
document.querySelector("#myImg").src = canvas.toDataURL();
}
/*Paper JS Setup for working in CodePen */
/* ====================== *
* 0. Initiate Canvas *
* ====================== */
// expose paperjs classes into global scope
paper.install(window);
// Only executed our code once the DOM is ready.
window.onload = function() {
// bind paper to the canvas
paper.setup('canvas2');
// paper.activate();
// Get a reference to the canvas object
var canvas = document.getElementById('canvas2');
var ctx = canvas.getContext('2d');
// console.log(ctx, image);
// ctx.drawImage(image, 0, 0);
// return;
// }
// Create a raster item using the image id='' tag
var image = document.querySelector('img');
var raster = new Raster(image);
// Hide the raster:
raster.visible = false;
// The size of our grid cells:
var gridSize = 15;
// Space the cells by 120%:
var spacing = 1
;
// As the web is asynchronous, we need to wait for the raster to load before we can perform any operation on its pixels.
raster.onLoad = function() {
// Since the example image we're using is much too large, and therefore has way too many pixels, lets downsize it to 40 pixels wide and 30 pixels high:
raster.size = new Size(40, 30);
for (var y = 0; y < raster.height; y++) {
for(var x = 0; x < raster.width; x++) {
// Get the color of the pixel:
var color = raster.getPixel(x, y);
// Create a circle shaped path:
var path = new Path.Circle({
center: new Point(x, y).multiply(gridSize),
radius: gridSize / 2 / spacing,
});
// Set the fill color of the path to the color
// of the pixel:
path.fillColor = color;
}
}
// Move the active layer to the center of the view, so all the created paths in it appear centered.
project.activeLayer.position = view.center;
}
}
I've tried giving the second canvas a different Id="canvas2" and referencing that, which I can see in the console. However, nothing appears in the second canvas and the paper.js script doesn't seem to execute, can someone help me understand why?
Please see also see link to the fiddle below:
https://jsfiddle.net/jmnes/o4Lpkfs6/1/
Alternatives method.
You don't need to capture the video, you don't need to capture the pixels using paper.js and raster. You don't need to find the color of each circle and draw it.
All these methods are slow, complex, and power hungry.
You can create a mask and mask out the circles, with the colors drawn from a smaller canvas with a res that matches the number off circles.
How to
Add one (main canvas) canvas to the DOM. This will display the result
Create 2 offscreen canvas.
One (color canvas) has the same resolution as the circles you want to display. Eg if you have 30 by 40 circle the canvas res should be 30 by 40
One (mask canvas) is the circle mask. It is the same resolution as the main canvas. Draw the circles all in one color on this canvas.
Then rendering once a frame
Draw the video on the color canvas to fit.
Turn off smoothing on the main canvas eg ctxMain.imageSmoothingEnabled = false
Draw the color canvas onto the main canvas to fit.
This will draw a color square at each circle position. ctx.drawImage(colorCanvas, 0, 0, mainCanvas.width, mainCanvas.height)
Set composite operation "destination-in" eg ctxMain.globalCompositeOperation = "destination-in"
Draw the mask canvas (canvas with circles on it) onto the main canvas. This will remove pixels outside each circle.
Restore default composite operation for the main canvas ctxMain.globalCompositeOperation = "source-over"
All done for a real-time FX on almost any device.
The above methods is the fastest way to render the effect you are after using the 2D API
I've implemented nativescript image picker plugin in my Nativescript -Angular code but I'm trying to figure out how to resize image picked from nativescript-imagepicker that can display as Account or Profile picture in circle
The selected image will be instance of ImageAsset, you may set the options with desired width and height then call use fromAsset method on ImageSource for resized image.
context
.authorize()
.then(function() {
return context.present();
})
.then(function(selection) {
selection.forEach(function(selected) {
// Set values for width, height, keepAspectRatio (boolean)
selected.options = {width, height, keepAspectRatio };
imageSourceModule.fromAsset(selected)
.then((imageSource) => {
// imageSource is resized one
});
});
}).catch(function (e) {
// process error
});
https://jsfiddle.net/diegojsrw/od12s9b4/14/
c.font = "100vh sans-serif";
c.fillStyle = "white";
c.fillText(fps.toFixed(0), w/2, 0);
Initially, the text's height seems fine.
However, when I resize the window, the text doesn't resize together. The text is constantly drawn on canvas (using requestAnimationFrame).
The text size is only re-adjusted when I switch to another tab then switch back to this tab.
Any clues?
You are facing a webkit bug. Both latests Chrome and Safari are concerned.
In the Canvas2D API, relative units/values should get computed at setting and this computed value will get saved and used.
This means that your relative 100vw value will get computed to its corresponding value in absolute px unit.
This is one of the reasons it is advised to always use absolute units from the canvas API (among others like tweaks in roundings etc.).
But if you really want to use this unit, then you have to set it everytime it has changed, so you could go blindly and inside your loop just set ctx.font again before calling fillText(), but for performances, I would advise you use a dirty flag, that would get raised in the window's resize event, and only update the ctx.font property when this flag is raised.
But this is only fine for browsers that do follow the specs...
I have no real clue as to when webkit browsers will compute this value, as even resetting the font property to something else won't do, and even setting it to an other value (e.g switching between 20vh and 21vh) won't do either...
So the only workaround I can see for now, is to actually compute yourself this value. For viewport size, that's not so hard (innerWidth / (100 / vw_val)), but even for other relative units, you can actually set this fontSize on the canvas directly and call getComputedStyle() on the canvas.
let dirtySize = true; // this is our resize flag
const ctx = canvas.getContext('2d');
let fontStyle = ' Arial, sans-serif';
anim(0);
// the animation loop
function anim(time) {
// call the drawing methods
draw(Math.round(time/1e2));
// lwoer the flags
dirtySize = false;
// do it again next frame
requestAnimationFrame(anim);
}
function draw(txt) {
// clear
ctx.clearRect(0,0,canvas.width, canvas.height);
// only if needed
if(dirtySize) {
// get the cpmputed style from our DOM element
const fontSize = getComputedStyle(canvas).fontSize;
// or could be
// const fontSize = (innerWidth / (100 / 20)) + 'px';
ctx.font = fontSize + fontStyle;
}
// draw everytime
ctx.fillText(txt, 0, 100);
}
// on window's resize event
window.addEventListener('resize',
evt => dirtySize = true, // raise our flag
{ passive: true }
);
#canvas {
font-size: 20vw;
}
<canvas id="canvas"></canvas>
I'm working with a function that uses an image to set a div's margin-top.
It finds the image height and the window height and sets the divs margin-top to the lesser of the two values. It works perfectly fine for all local browsers (IE, Chrome, Firefox).
When I upload it to GitHub it fails to recognize the image height however. Now when I run the code below on GitHub the console.log of the image height is 0. When I run it locally the console.log of the image height is correct. The image is loaded on GitHub, so it's not an issue of the image not making into the web page.
It seems like the script runs before the image loads on GitHub, but not locally. Anyone have any ideas?
var portfolioMargin = function() {
var windowHeight = window.innerHeight;
var imageHeight = $('#imageWrap img').height();
//if windowheight is bigger than image height make portfolio div margin equal to image height, else do the opposite
console.log("window height " + windowHeight);
console.log("image height " + imageHeight);
if (windowHeight > imageHeight) {
$('#portfolio').css('margin-top', imageHeight);
} else {
$('#portfolio').css('margin-top', windowHeight);
}
};//end portfolioMargin function
So I figured it out I think. You have to wrap the function in a window.load function to make sure all images have been loaded. From what I understand this won't work for dynamically added images however. Here is the code that fixed it:
//make sure images have loaded before running image height
$(window).load(function() {
portfolioMargin();
});
In image tag, if we don't supply width and height property, we will get nothing when retrieving the width and the height of the image. I am using the canvas element to load an image and scale it proportionally. In order to do this, I have to get the actual image size. Is it possible to do that in html 5?
The HTMLImageElement has two properties for this, naturalWidth and naturalHeight. Use those.
As in:
var img = new Image();
img.addEventListener('load', function() {
// once the image is loaded:
var width = img.naturalWidth; // this will be 300
var height = img.naturalHeight; // this will be 400
someContext.drawImage(img, 0, 0, width, height);
}, false);
img.src = 'http://placekitten.com/300/400'; // grab a 300x400 image from placekitten
It is wise to set source only after the event listener is defined, see Phrogz's exploration on that here: Should setting an image src to data URL be available immediately?
You cannot retrieve width/height before image has been loaded.
Try something like:
// create new Image or get it right from DOM,
// var img = document.getElementById("myImage");
var img = new Image();
img.onload = function() {
// this.width contains image width
// this.height contains image height
}
img.src = "image.png";
Anyhow onload will not fire if image has been loaded before script execution. Eventually you can embed script in html <img src="test.jpg" onload="something()">
if I understand you correctly, you can use the getComputedStyle method.
var object = document.getElementById(el);
var computedHeight = document.defaultView.getComputedStyle(object, "").getPropertyValue("width");
Not fully understood your question.
But you can use javascript to get the width and height of the image.
and then pass it into
/ Five arguments: the element, destination (x,y) coordinates, and destination
// width and height (if you want to resize the source image).
context.drawImage(img_elem, dx, dy, dw, dh);
while drawing image on canvas.
or check this if it helps
http://jsfiddle.net/jjUHs/