In the past I came across http://www.jacklmoore.com/zoom/ which was a great find and very simple to use for a variety of images. I am looking for a grab-zoom feature using pure-javascript rather than jQuery. Is there any Pure-Javascript solution for this? I've attempted this with no luck so far:
Javascript:
var imgSize = 1;
function zoomIn() {
imgSize += 0.1;
document.body.style.imgSize = imgSize + "em";
}
function zoomOut() {
imgSize -= 0.1;
document.body.style.imgSize = imgSize + "em";
}
HTML
<img src="picture.png" value="+" onClick="zoomIn()"/>
Thanks in advance for any helpful tips!
The general idea is to display the smaller sized image ("original") and when the mouse is hovering over the container, the background image of the container is revealed. The background image is large, and the CSS background is clipped by the container's size. Mouse events are tracked. You'll have to work out the measurement and math yourself.
<div id="imageview" style="position:relative;width:300px;height:200px;"
>
<img src="300x200.jpg" id="original" onmouseover="this.style.display='none';">
</div>
<script>
document.getElementById('imageview').onmouseover=function(e){
document.getElementById('original').style.display='none';
var x,y;
if (e) {x=e.clientX;y=e.clientY;} else {x=event.clientX; y=event.clientY;}
document.getElementById('imageview').orgx=x;
document.getElementById('imageview').orgy=y;
}
document.getElementById('imageview').onmousemove=function(e){
var x,y;
if (e) {x=e.clientX;y=e.clientY;} else {x=event.clientX; y=event.clientY;}
var orgx=document.getElementById('imageview').orgx;
var orgy=document.getElementById('imageview').orgy;
//now you have x, y, orgx, and org y, so you can do some math
// ...
var posx, posy;
document.getElementById('imageview').backgroundImage='url(600x400.jpg)';
document.getElementById('imageview').backgroundPosition=-1*posx+'px '+ -1*posy+'px';
}
</script>
Please give this image zooming library (written by me) a try: https://github.com/kingdido999/zooming
It's implemented in pure JavaScript with no extra dependency.
Related
I am using this library: https://www.jacklmoore.com/zoom/
It adds a zoom function when hovering over an image. I did add the library in my theme and added this jQuery code to my js file:
$(document).ready(function(){
$('.head-image img').zoom();
});
This is the HTML where the image is located:
<div class="head-image">
<img src="<?php the_post_thumbnail_url('full'); ?>" class="img-fluid">
</div>
When I hover the image on the webpage nothing changes but if I look in the inspector I do see that the zoomImg class is added and the CSS is changing but I dont see the image zooming.
Here is the webpage URL: https://www.dev.ruitershopboxmeer.nl/paard/zadels-en-toebehoren/zadeldekjes/kingsland-zadeldekje-carin/
Does someone know why the image is not zooming?
Thanks for your time!
First fix the error in the beginning of the page (line 14 generated HTML)
<script>if(flycart_woo_discount_rules_strikeout_script_executed == undefined){jQuery( document ).ready( /* .... */
This needs to be moved at the end of the body to avoid issues
Next, make sure to include JQuery and Zoom correctly (from demo)
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'></script>
<script src='path/to/jquery.zoom.js'></script>
The imported JQuery is 3.4.1 and I am not sure Zoom is still compatible with it as demo was using 1.10.2.
I have an alternate solution to your requirement here:
const img=document.querySelector('.image');
const pro=document.querySelector('.image img');
img.style.width=(pro.clientWidth)+'px';
var zoomSize = pro.clientHeight*6;
img.addEventListener('mousemove', printPosition);
img.addEventListener('mouseout', back);
function getPosition(e) {
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
return {
x,
y
}
}
function printPosition(e) {
var position = getPosition(e);
xpos=position.x * (100/pro.clientWidth);
ypos=position.y * (100/pro.clientHeight);
pro.style.transition="0s";
pro.style.transform='translate('+xpos*-5+'%, '+ypos*-5+'%)';
pro.style.height=zoomSize+"px";
console.log('X: ' + xpos + ' Y: ' + ypos);
}
function back(e) {
pro.style.transform='translate(0px, 0px)';
pro.style.height='100%';
pro.style.transition="1s";
}
https://codepen.io/thevectorator/pen/NWGeBPm
I am trying to write code that resizes an SVG overlay on top of an image. The server I am working with returns both the image and via an API, a list of polygon points I need to overlay on top of the image.
This is what it should look like (the image below is a correctly aligned SVG layer). The image size is 1280x720 (I've scaled it down)
What I need to do in my app (ionic v1 app) is to make sure the SVG overlay resizes as the browser window resizes and it seems to be very hard. Here is my approach:
I am trapping a window resize event and when the image is resized, I scale the SVG polygon points relative to the size of the drawn window as it seems there is really no way to "automatically" scale the SVG by the browser like it does with an image.
Here is my code pen as you see it doesn't work as intended when I rescale (and for that matter in when its full size the overlays are not accurate). The overlays don't look accurate and when I resize it all messed up. Can someone help?
Given SO needs a code block for codepen links here it is, but its just easier to look at the codepen if you want to run it
CSS:
.imagecontainer{position:relative; margin:0 auto;}
.zonelayer
{
position:absolute;
top:0;
left:0;
background:none;
}
.zonelayer polygon {
fill-opacity: 0.25;
stroke-width: 2px;
}
.Active {
stroke: #ff0000;
fill: #ff0000;
}
HTML code:
<ion-content>
image:{{disp}}<br/>
<small>points: <span ng-repeat="item in zoneArray">{{item}}</span></small>
<div class="imagecontainer">
<img id="singlemonitor" style="width:100vw; height:100vh;object-fit:contain" ng-src="http://m9.i.pbase.com/o9/63/103963/1/164771719.2SfdldRy.nphzms.jpeg" />
<div class="zonelayer">
<svg ng-attr-width="{{cw}}" ng-attr-height="{{ch}}" class="zonelayer" ng-attr-viewBox="0 0 {{cw}} {{ch}}">
<polygon ng-repeat="item in zoneArray" ng-attr-points="{{item}}" class="Active"/> </polygon>
</svg>
</div>
</div>
</ion-content>
JS controller:
window.addEventListener('resize', liveloaded);
liveloaded();
// credit: http://stackoverflow.com/questions/41411891/most-elegant-way-to-parse-scale-and-re-string-a-string-of-number-co-ordinates?noredirect=1#41411927
function scaleCoords(string, sx, sy) {
var f = [sx, sy];
return string.split(' ').map(function (a) {
return a.split(',').map(function (b, i) {
return Math.round(b * f[i]);
}).join(',');
}).join(' ');
}
function liveloaded()
{
$timeout (function () {
console.log ("IMAGE LOADED");
var img =document.getElementById("singlemonitor");
//var offset = img.getBoundingClientRect();
$scope.cw = img.clientWidth;
$scope.ch = img.clientHeight;
$scope.vx = img.offsetWidth;
$scope.vy = img.offsetHeight;
var rect = img.getBoundingClientRect();
//console.log(rect.top, rect.right, rect.bottom, rect.left);
$scope.disp = img.clientWidth+ "x"+img.clientHeight + " with offsets:"+$scope.vx+"/"+$scope.vy;
$scope.zoneArray = [
"598,70 700,101 658,531 516,436",
"531,243 687,316 663,593 360,717 191,520",
"929,180 1108,248 985,707 847,676",
"275,17 422,45 412,312 271,235",
];
var ow = 1280;
var oh = 720;
for (var i=0; i < $scope.zoneArray.length; i++)
{
var sx = $scope.cw/ow;
var sy = $scope.ch/oh;
$scope.zoneArray[i] = scaleCoords($scope.zoneArray[i],sx,sy);
console.log ("SCALED:"+$scope.zoneArray[i]);
}
});
}
There are a couple of issues with your code.
The main problem is you can't use ng-attr-viewBox, because angular will "normalise" the attribute to lower case. It turns the attribute into viewbox (lower case B) which is (currently) invalid. viewBox is case sensitive.
The solution is to use a special trick of Angular to preserve camel-case. If you use ng-attr-view_box, it will generate the correctly camel-cased attribute name of viewBox.
<svg width="100vw" height="100vh" class="zonelayer" ng-attr-view_box="0 0 {{cw}} {{ch}}">
The other thing is that you are using the wrong width and height values for the viewBox. You need to use the natural/intrinsic image dimensions in your viewBox.
$scope.cw = img.naturalWidth;
$scope.ch = img.naturalHeight;
Link to updated code pen
I've successfully programmed my jQuery slime menu, and now it works beautiful. My only problem is that I move the arrow and the ending circle (the icon) of the slime separately, so if you move the cursor too away from the starting point, it will not connect to the slime precisely. It must be a rounding issue. Here's an image of what I'm talking about:
And here's the fiddle I'm working on:
http://jsfiddle.net/41Lcj653/4/
EDIT (Working): http://jsfiddle.net/41Lcj653/7/
Can anyone help with this issue? I use CSS transformations, and JS for update the CSS rules in each step.
The JS part of the code:
$(function(){
$(window).mousemove(function(e){
moveslime(e);
});
});
function moveslime(e){
var rad = $('.arrow').height() / 2;
var ofs = $('.arrow').offset();
var mPos = {x: e.pageX-25-rad, y: e.pageY-25-rad};
var dir = Math.round( -(Math.atan2(mPos.x, mPos.y)) / (Math.PI/180) );
$('.arrow').css('transform','rotate('+dir+'deg)');
$('.arrow').css('border-width','0 25px '+pdist(0, 0, mPos.x, mPos.y)+'px 25px');
$('.bubble').css('left', mPos.x+'px').css('top', mPos.y+'px');
}
function pdist(x1,y1,x2,y2) {
return Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
}
the reason you see this 'not precisely connected' is that rotate goes in 360 steps (the 360 degrees of a circle). when you are near the center the effect can be neglected, but the more you get away from the center (increasing circle circumference!) the visible gap between the degrees increases.
Maybe try this with svg?
actually you can use float numbers a degree .. so dont round the deg!
https://jsfiddle.net/41Lcj653/5/
// without math.round
var dir = -(Math.atan2(mPos.x, mPos.y)) / (Math.PI/180);
Some jQuery method like height rounds decimals. You could try this:
$(".arrow")[0].getBoundingClientRect().height
More information: https://developer.mozilla.org/es/docs/Web/API/Element/getBoundingClientRect
So Im trying to make something where the user is able to drag planets along their orbits and it will continuously update the other planets. Ideally I would like this to work with ellipses too.
So far I can drag an image node with jquery and check/change the coordinates, but i cannot update the position reliably while the user is dragging the object. I know there is an axis and a rectangle containment for draggable but this doesn't really help me.
I have a site for calculating planetary orbits http://www.stjarnhimlen.se/comp/ppcomp.html and a formula i think should help me if i can figure out how to constrain the draggable object with coordinate checks Calculating point on a circle's circumference from angle in C#?
But it seems like there should be an easier way to have a user drag a sphere along a circular track while it updates coords for other spheres
here's what i have so far. It's not much
http://jsfiddle.net/b3247uc2/2/
Html
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
Js
var $newPosX = 100,
$newPosY = 100;
//create image node
var x = document.createElement("IMG");
x.src = "http://upload.wikimedia.org/wikipedia/commons/a/a4/Sol_de_Mayo_Bandera_Argentina.png";
x.width = 100;
x.height = 100;
x.id = "sun";
x.hspace = 100;
x.vspace = 100;
document.body.appendChild(x);
//coords
var text = document.createTextNode($newPosX + " " + $newPosY);
document.body.appendChild(text);
//make sun draggable and update coords
$("#sun").draggable({
drag: function (event, ui) {
$newPosX = $(this).offset().left;
$newPosY = $(this).offset().top;
}
});
//0 millisecond update for displayed coords
setInterval(check, 0);
function check() {
//tries to constrain movement, doesn't work well
/*
if ($newPosX > 300) {
$("#sun").offset({
left: 200
});
}
*/
text.nodeValue = ($newPosX + " " + $newPosY);
}
Edit:
I found this and am trying to modify it to suit my purposes but have so far not had luck.
http://jsfiddle.net/7Asn6/
Ok so i got it to drag
http://jsfiddle.net/7Asn6/103/
This is pretty close to what I want but can be moved without being clicked on directly
http://jsfiddle.net/7Asn6/104/
Ok final edit on this question. This one seems to work well and have fixed my problems. I would still very much like to hear peoples implementation ideas or ideas to make it work smoother.
http://jsfiddle.net/7Asn6/106/
I am trying to implement some kind of Zoom/Pan features to maps generated with the google geochart API. There are some scripts online to zoom/pan svg images, but I am not succeeding in implementing them to the SVGs that the geochart api generates.
I am trying the SVGPan library http://code.google.com/p/svgpan/
The code I'm using to append the script to the SVG is:
google.visualization.events.addListener(chart, 'ready', function () {
var script = document.createElementNS('http://www.w3.org/2000/svg', 'script');
script.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'http://www.cyberz.org/projects/SVGPan/SVGPan.js');
var svg = document.getElementsByTagName('svg')[0];
svg.appendChild(script);
});
Here's the jsfiddle:
http://jsfiddle.net/cmoreira/CetaA/
With Firebug I can see the script is beeing place on the svg, but nothing happens, it doesn't implement the features in the svg, as expected.
I am not sure if this line is correct, since I didn't find any example online:
var script = document.createElementNS('http://www.w3.org/2000/svg', 'script');
Am I doing something wrong, or what I'm trying to do will be impossible?
Thanks for you help!
Cheers
Carlos
After some experiments, I was able to find a simple solution and since there were not any valuable answers so far, I decided to share what I have so far.
I decided to do it with CSS, redrawing the map with different values on zoom in/out and hide the overflow with CSS.
Here's a working example:
http://jsfiddle.net/cmoreira/CCUpf/
CSS
#canvas {
width:400px;
height:300px;
overflow:hidden;
}
#visualization {
top:0px;
left:0px;
}
Zoom/Pan Javascript
function zoomin() {
mw = mw+50;
mh = mh+50;
x = x-25;
y = y-25;
document.getElementById('visualization').style.top = y +'px';
document.getElementById('visualization').style.left = x +'px';
drawVisualization(mw,mh);
}
function zoomout() {
if(mw > 600) {
mw = mw-50;
mh = mh-50;
x = x+25;
y = y+25;
document.getElementById('visualization').style.top = y +'px';
document.getElementById('visualization').style.left = x +'px';
drawVisualization(mw,mh);
}
}
function left() {
x = x-50;
document.getElementById('visualization').style.left = x +'px';
}
function right() {
x = x+50;
document.getElementById('visualization').style.left = x +'px';
}
function up() {
y = y-50;
document.getElementById('visualization').style.top = y +'px';
}
function down() {
y = y+50;
document.getElementById('visualization').style.top = y +'px';
}
I know this is a very poor zoom/pan feature for the google geochart API, but it's something, right?
Any improvements to this simple aproach would be welcomed.
Thanks!
I would recommend you to try jVectorMap instead. It has support for the zoom/pan with mouse or touch events.