Hammer.js Pinch-to-zoom not working - image

UPDATE: Got a jsfiddle up # http://jsfiddle.net/gacDy/7/ , however, I can't even seem to get this working correctly. I'll keep working on it, but hopefully it'll help.
I'm using Hammer.js for an app I'm working on. For now, I've got a demo that I got on the web somewhere that I'm using to figure out how to make this work. For the demo I have two images (I'll post screenshots below) that I'm trying to get to zoom independently with hammer.js.
As things are right now, both images zoom, but the second one zooms into the region where the first image is. (See screenshots below)
Pre-zoom image:
Post-zoom image:
Code for images:
<div id="zoom2">
<img src="Chrysanthemum.jpg" alt="" width="600" height="377" />
</div>
<div id="zoom">
<img src="waldo.jpg" alt="" width="600" height="377" />
</div>
Functions and such:
<div id="debug"></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="hammer.js"></script>
<script src="jquery.hammer.js"></script>
<script src="jquery.specialevent.hammer.js"></script>
<script>
var debug_el = $("#debug");
// disable the dragging of images on desktop browsers
$("img").bind("dragstart", function() {
return false;
});
$(function(){
var zoom = new ZoomView('#zoom','#zoom :first');
});
function ZoomView(container, element) {
container = $(container).hammer({
prevent_default: true,
scale_treshold: 0,
drag_min_distance: 0
});
element = $(element);
// prefixes
var vendorPrefixes = ["", "-webkit-", "-moz-", "-o-", "-ms-", "-khtml-"];
var displayWidth = container.width();
var displayHeight = container.height();
//These two constants specify the minimum and maximum zoom
var MIN_ZOOM = 1;
var MAX_ZOOM = 5;
var scaleFactor = 1;
var previousScaleFactor = 1;
//These two variables keep track of the X and Y coordinate of the finger when it first
//touches the screen
var startX = 0;
var startY = 0;
//These two variables keep track of the amount we need to translate the canvas along the X
//and the Y coordinate
var translateX = 0;
var translateY = 0;
//These two variables keep track of the amount we translated the X and Y coordinates, the last time we
//panned.
var previousTranslateX = 0;
var previousTranslateY = 0;
//Translate Origin variables
var tch1 = 0,
tch2 = 0,
tcX = 0,
tcY = 0,
toX = 0,
toY = 0,
cssOrigin;
var last_drag_event;
container.bind("transformstart", function(event){
//We save the initial midpoint of the first two touches to say where our transform origin is.
tch1 = [event.touches[0].x, event.touches[0].y];
tch2 = [event.touches[1].x, event.touches[1].y];
tcX = (tch1[0]+tch2[0])/2;
tcY = (tch1[1]+tch2[1])/2;
toX = tcX;
toY = tcY;
cssOrigin = toX +"px "+ toY +"px";
});
container.bind("transform", function(event) {
scaleFactor = previousScaleFactor * event.scale;
scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM));
transform(event);
});
container.bind("transformend", function(event) {
previousScaleFactor = scaleFactor;
});
container.bind("drag", function(event) {
cssOrigin = (toX + (toX-event.position.x) / scaleFactor) +"px " +
(toY + (toY-event.position.y) / scaleFactor) +"px";
transform(event);
last_drag_event = event;
});
container.bind("dragend", function(event) {
toX += ((toX - last_drag_event.position.x) / scaleFactor);
toY += ((toY - last_drag_event.position.y) / scaleFactor);
cssOrigin = toX +"px "+ toY +"px";
transform(event);
debug_el.text('TX: '+toX+' TY: '+toY);
});
function transform(event) {
//We're going to scale the X and Y coordinates by the same amount
var cssScale = "scale("+ scaleFactor +")";
var props = {};
$(vendorPrefixes).each(function(i, vendor) {
props[vendor +"transform"] = cssScale;
props[vendor +"transform-origin"] = cssOrigin;
});
element.css(props);
debug_el.text('TX: '+translateX+' TY: '+translateY+' '+element.css('-webkit-transform-origin'))
}
}
</script>
-- I duplicated the above code and changed any references to the first image to reference the second image in order to make the second image zoomable. But like I mentioned it's not working correctly. I've tried changing around all my variable names in case I missed a reference to the 1st image that could be causing this overlap but nothing has helped.
EDIT: This may also be pertinent:
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<style>
#zoom {
height: 377px;
width: 600px;
overflow: hidden;
position:relative;
background: #eee;
border: solid 1px #ccc;
}
</style>
<meta name="viewport2" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<style>
#zoom2 {
height: 377px;
width: 600px;
overflow: hidden;
position:static;
background: #eee;
border: solid 1px #ccc;
}
</style>
I just need help figuring out how to keep the second image from disappearing into the 1st image when zooming. I'd appreciate any help I can get. Thanks all.

Related

Why is there so much time in between animation code and next animation frame?

I'm implementing a game using a canvas as the renderer, and there are some points where there seem to be excessive "waits" between render frames and I have no idea what to think of this.
I've been working on this for the past few weeks and for the most part, there haven't really been issues. However, when there are a lot of things on screen there is a "wait" for some reason.
It takes about the same amount of time that the rendering code does before "composite layers" is called. I don't know if this is something that I can prevent or if it is just something that I have to live with. I'm only getting to the point where I'm going below 60 fps in extreme situations anyway.
Another example:
index.js
window.onload = () => {
const width = 1280;
const height = 720;
const canvas = document.getElementById("game-canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
function renderLoop() {
console.time("render");
// Do render and request next frame
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < 13000; i++) {
// Not real code this is just to demonstrate the issue
ctx.fillRect(i % width, 10 * Math.floor(i / (width)), 10, 10);
}
console.timeEnd("render");
requestAnimationFrame(renderLoop);
}
requestAnimationFrame(renderLoop);
}
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
canvas {
border: 2px solid black;
display: inline-block;
vertical-align: top;
}
</style>
</head>
<body>
<script src="./index.js"></script>
<canvas id="game-canvas"></canvas>
</body>
</html>

Circular Slider using Jquery

How to slide mouse in circular ?
Draw an arc and a mouse pointer in a canvas. Mouse should be drag gable on the circular path?
//function to create mouse event to drag the mouse hover the arc
function mousedrag() {
var canvasoffset = $(this.canvas).offset();
var offsetX = canvasoffset.left;
var offsetY = canvasoffset.top;
var mouseX = parseInt(e.offsetX || e.clientX - offsetX);
var mouseY = parseInt(e.offsetY || e.clientY - offsetY);
var radius = this.width / 2;
var twoPI = 2 * Math.PI;
var toRad = twoPI / 360;
var r_width = this.width * 0.8;
var radial_Angle = Math.atan2(mouseY - radius,mouseX - radius);
var p_side_x = radius + r_width * Math.cos(radial_Angle);
var p_side_y = radius + r_width * Math.sin(radial_Angle);
var p_mouse_x = radius + ((r_width+10) * Math.sin(radial_Angle));
var p_mouse_y = radius + ((r_width+ 10) * Math.sin(radial_Angle));
var imgData = this.ctx.getImageData(p_side_x, p_side_y, 1, 1).data;
var selectedColor = new Color(imgData[0], imgData[1], imgData[2]);
clearDraw();
renderSpectrum();
renderMouse(p_side_x, p_side_y, p_mouse_x, p_mouse_y);
}
mouse handle does not slide properly.
You can't actually force the mouse to be constrained into a circle.
But you can calculate the mouse position relative to a centerpoint.
// define a centerpoint
var cx=150;
var cy=150;
var angleVersusCenter=0;
// listen for mouse moves
function handleMouseMove(e){
// get the mouse position
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// set the current radian angle of the mouse
// versus the centerpoint
var angleVersusCenter = Math.atan2( mouseY-cy, mouseX-cx );
}
A Demo: http://jsfiddle.net/m1erickson/z6cQB/
Here is the jQuery roundSlider plugin for your requirement, check here http://roundsliderui.com/. This might helps you.
This roundslider having the similar options like the jQuery ui slider. It support default, min-range and range slider type. Not only the round slider it also supports various circle shapes such as quarter, half and pie circle shapes.
For more details check the demos and documentation page.
Please check the demo from jsFiddle.
Live demo:
$("#slider").roundSlider({
width: 10,
handleSize: "+8",
value: "40"
});
$("#half-slider").roundSlider({
width: 10,
circleShape: "half-top",
handleSize: "+8",
value: "80"
});
.rs-control {
display: inline-block;
float: left;
margin-left: 30px;
}
.rs-control .rs-path-color {
background-color: #e9e9e9;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.roundslider/1.0/roundslider.min.js"></script>
<link href="https://cdn.jsdelivr.net/jquery.roundslider/1.0/roundslider.min.css" rel="stylesheet"/>
<div id="slider" class="rslider"></div>
<div id="half-slider" class="rslider"></div>
Screenshots with different appearances:
Check more details about different theme from here.

How to render geojson with three.js and d3.js

I use three.js r49, d3.v2.js and d3-threeD.js i want to render my city(Mashhad) with three.js
but i got a problem i can render europian countries with these codes but i cant render with existing json file.
d3.js Ref
d3-threeD.js Ref
these are my codes:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>GEO Bar</title>
<link rel="stylesheet" href="">
<script type="text/javascript" src="./scripts/jquery-1.7.2.js"></script>
<script type="text/javascript" src="./scripts/d3.v2.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/three.js/r49/Three.min.js"></script>
<script type="text/javascript" src="./scripts/d3-threeD.js"></script>
<script type="text/javascript" src="./scripts/constants.js"></script>
<script type="text/javascript" src="./scripts/util-geo.js"></script>
<script type="text/javascript" src="./scripts/script.js"></script>
<style type="text/css">
.btns{
position: fixed;
right: 100px;
top: 100px;
}
.btn{
width: 40px;
height: 60px;
background-color: #999;
margin-top: 5px;
text-align: center;
color: #111;
}
.btn > div{
margin-bottom: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="chart"></div>
<div class="btns">
<div class="btn x">
<div class="plus">+</div>X
<div class="minus">-</div>
</div>
<div class="btn y">
<div class="plus">+</div>Y
<div class="minus">-</div>
</div>
<div class="btn z">
<div class="plus">+</div>Z
<div class="minus">-</div>
</div>
</div>
</body>
</html>
constants.js codes:
var appConstants = {
TRANSLATE_0 : -360,
TRANSLATE_1 : 10040,
SCALE : 60000
}
util-geo.js codes:
var geons = {};
geons.geoConfig = function() {
this.TRANSLATE_0 = appConstants.TRANSLATE_0;
this.TRANSLATE_1 = appConstants.TRANSLATE_1;
this.SCALE = appConstants.SCALE;
this.mercator = d3.geo.mercator();
this.path = d3.geo.path().projection(this.mercator);
this.setupGeo = function() {
var translate = this.mercator.translate();
translate[0] = this.TRANSLATE_0;
translate[1] = this.TRANSLATE_1;
this.mercator.translate(translate);
this.mercator.scale(this.SCALE);
}
console.log(2,this.path);
}
// geoConfig contains the configuration for the geo functions
geo = new geons.geoConfig();
script.js codes:
(function($) {
$(function(){
// get the correct geo for d3s
geo.setupGeo();
var
dataURL = "area.json",
scene,
renderer,
camera;
btnXPlus = $(".btns .x .plus"),
btnXMinus = $(".btns .x .minus"),
btnYPlus = $(".btns .y .plus"),
btnYMinus = $(".btns .y .minus"),
btnZPlus = $(".btns .z .plus"),
btnZMinus = $(".btns .z .minus"),
translate = geo.mercator.translate();
// get the data
$.getJSON( dataURL, function(data, textStatus, jqXHR) {
initScene();
addGeoObject();
renderer.render( scene, camera );
// Set up the three.js scene. This is the most basic setup without
// any special stuff
function initScene() {
// set the scene size
var
WIDTH = 600,
HEIGHT = 600;
// set some camera attributes
var
VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 1, FAR = 10000;
// create a WebGL renderer, camera, and a scene
renderer = new THREE.WebGLRenderer({antialias:true});
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
scene = new THREE.Scene();
// add and position the camera at a fixed position
scene.add(camera);
camera.position.z = 550;
camera.position.x = 0;
camera.position.y = 550;
console.log("scene.position: ",scene.position);
camera.lookAt( scene.position );
// start the renderer, and black background
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor(0x321);
// add the render target to the page
$("#chart").append(renderer.domElement);
// add a light at a specific position
var pointLight = new THREE.PointLight(0xFFFFFF);
scene.add(pointLight);
pointLight.position.x = 800;
pointLight.position.y = 800;
pointLight.position.z = 800;
// add a base plane on which we'll render our map
var planeGeo = new THREE.PlaneGeometry(10000, 10000, 10, 10);
var planeMat = new THREE.MeshLambertMaterial({color: 0x666699});
var plane = new THREE.Mesh(planeGeo, planeMat);
// rotate it to correct position
plane.rotation.x = -Math.PI/2;
scene.add(plane);
console.log(1);
}
// add the loaded gis object (in geojson format) to the map
function addGeoObject() {
// keep track of rendered objects
var meshes = [];
var colors = [];
var averageValues = [];
var totalValues = [];
// keep track of min and max, used to color the objects
var maxValueAverage = 0;
var minValueAverage = -1;
// keep track of max and min of total value
var maxValueTotal = 0;
var minValueTotal = -1;
// convert to mesh and calculate values
for (var i = 0 ; i < data.features.length ; i++) {
console.log(data.features[i]);
var geoFeature = data.features[i];
var feature = geo.path(geoFeature);
console.log("feature:",feature);
// we only need to convert it to a three.js path
var mesh = transformSVGPathExposed(feature);
console.log(mesh);
// add to array
meshes.push(mesh);
// we get a property from the json object and use it
// to determine the color later on
var value = parseInt(geoFeature.properties.bev_dichth);
if (value > maxValueAverage) maxValueAverage = value;
if (value < minValueAverage || minValueAverage == -1) minValueAverage = value;
averageValues.push(value);
// var style = JSON.parse(geoFeature.properties.style);
// colors.push(hexToRgb(style.strokeColor));
// colors.push(style.strokeColor);
// and we get the max values to determine height later on.
value = parseInt(geoFeature.properties.aant_inw);
if (value > maxValueTotal) maxValueTotal = value;
if (value < minValueTotal || minValueTotal == -1) minValueTotal = value;
totalValues.push(value);
}
console.log(averageValues,totalValues,colors);
// we've got our paths now extrude them to a height and add a color
for (var i = 0 ; i < averageValues.length ; i++) {
// create material color based on average
var scale = ((averageValues[i] - minValueAverage) / (maxValueAverage - minValueAverage)) * 255;
var mathColor = gradient(Math.round(scale),255);
console.log(scale,mathColor);
var material = new THREE.MeshLambertMaterial({
color: mathColor
});
// var material = new THREE.MeshLambertMaterial({
// // color: hexToRgb(colors[i])
// });
// material.color.setHex(colors[i]);
console.log("material:", material);
// create extrude based on total
var extrude = ((totalValues[i] - minValueTotal) / (maxValueTotal - minValueTotal)) * 100;
var shape3d = meshes[i].extrude({amount: Math.round(extrude), bevelEnabled: false});
console.log("extrude: ",extrude, "shape3d:", shape3d);
// create a mesh based on material and extruded shape
var toAdd = new THREE.Mesh(shape3d, material);
// rotate and position the elements nicely in the center
toAdd.rotation.x = Math.PI/2;
toAdd.translateX(-490);
toAdd.translateZ(50);
toAdd.translateY(extrude/2);
console.log("toAdd: ",toAdd);
// add to scene
scene.add(toAdd);
}
}
// simple gradient function
// function gradient(length, maxLength) {
// var i = (length * 255 / maxLength);
// var r = i;
// var g = 255-(i);
// var b = 0;
// var rgb = b | (g << 8) | (r << 16);
// console.log(rgb);
// return rgb;
// }
function gradient(color, maxLength) {
var i = (length * 255 / maxLength);
var r = i;
var g = 255-(i);
var b = 0;
var rgb = b | (g << 8) | (r << 16);
console.log("rgb: ",rgb);
return rgb;
}
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
// return result ? {
// r: parseInt(result[1], 16),
// g: parseInt(result[2], 16),
// b: parseInt(result[3], 16)
// } : null;
return result ? parseInt(result[1], 16) | (parseInt(result[2], 16) << 8) | (parseInt(result[3], 16) << 16) : null;
}
});
btnXPlus.click(function(){
camera.position.x +=10;
console.log(camera.position.x);
renderer.render( scene, camera );
});
btnXMinus.click(function(){
camera.position.x -=10;
console.log(camera.position.x);
renderer.render( scene, camera );
});
btnYPlus.click(function(){
camera.position.y +=10;
console.log(camera.position.y);
renderer.render( scene, camera );
});
btnYMinus.click(function(){
camera.position.x -=10;
console.log(camera.position.y);
renderer.render( scene, camera );
});
btnZPlus.click(function(){
camera.position.z +=10;
console.log(camera.position.z);
renderer.render( scene, camera );
});
btnZMinus.click(function(){
camera.position.z -=10;
console.log(camera.position.z);
renderer.render( scene, camera );
});
});
})(jQuery);
my geo json file: omidgharib.ir/area.json

Make jpeg canvas animation "responsive"

Improve HTML5 Canvas frame by frame JPG animation to fully cache before animating
The above code snippet is great. I'd like to be able to apply new widths with css/media queries to the canvas that holds the jpgs. Is there a way to add that to the above code?
when I tried it my jpg's became wildly oversized.
It appears in the above code that the height and width declared in js for the image and the height and width on the canvas tag need to match or things get wonky.
I want to dynamically call the image width with CSS and media queries.
thanks
<style type="text/css">
/*CSS for full screen animation.You may want to remove this*/
html,body {
height:100%;
width:100%;
padding:0;
margin:0;
}
/*ID for Canvas JPG Animation - Sets size, background image and loader*/
#anim {
background-image:url('images/icon_loading_75x75.gif'),url('images/t5.png');
/*Center=Loading GIF, Left Top= Placeholder Image*/
background-position: center, left top;
background-repeat: no-repeat;
height:500px;
width:660px;
}
</style>
<script type="text/javascript">
function draw() {
var ctx = document.getElementById('anim').getContext("2d");
var start = 1, stop = 121,cur=start,imgArr=[];
//Pre-loads Images
var loadLoop = function() {
var img = document.createElement("img");
img.onload = function() {
imgArr.push(this);
cur++;
if(cur > stop) {
// all images preloaded
animate();
}
else {
loadLoop();
}
}
//img.src = "jpg_80/t5_"+(cur)+".jpg";
img.src = "http://html5canvas.syntheticmedia.net/jpg_80/t5_"+(cur)+".jpg";
//jpg_80/t5_88.jpg
}
loadLoop();
//Canvas JPG Animation
function animate() {
var timer = setInterval(function() {
ctx.drawImage(imgArr.shift(), 0, 0 );
if(imgArr.length == 0) {
// no more frames
clearInterval(timer);
}
//Framerate # 24 Frames per Second
},1000/24);
}
}
</script>
<script src="modernizr-2.6.2.min.js" type="text/javascript">
</script>
<body>
<!-- HTML5 Canvas Animation-->
<canvas id="anim" width="660" height="500"></canvas>
<script>
//call after page loaded
window.onload = draw;
</script>
</body>

Full screen scaling background image overlays

I have a page whose background image scales as the browser re-sizes. What I'm trying to figure out is how to make the blue marker image scale and maintain position in proportion to the background. For example, if the blue marker were on the tip of the harbor, as I scaled the browser down, I'd want that marker to stay on the tip of the harbor and shrink in size proportionally with the browser's new dimensions.
Anyone have any ideas that will point me in the right direction?
I used the below method to find the browser size, but I think my math's a little off. You can view the live example here:
http://mikeheavers.com/stage/full_screen_map/
The marker gets really off if you scale it in one direction more than the other.
<style type="text/css">
html {
background: url(images/antigua.jpeg) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
#infoDiv {
background: white;
padding: 20px;
width: 200px;
position:absolute;
}
#map_canvas {
position:absolute ;
}
.marker {
position:absolute;
left: 800px;
top: 400px;
height: 20px;
width: 20px;
background: #ff0000;
}
</style>
<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.4.min.js"></script>
<div id="infoDiv">
</div>
<div id="markers">
<div class="marker">
</div>
</div>
<script type="text/javascript">
$(document).ready(function()
{
var myWidth = window.innerWidth;
var leftVal = $("#markers").children().css('left');
var leftValNumber = parseFloat(leftVal);
var leftRatio = leftValNumber / myWidth;
var leftValPos;
var myHeight = window.innerHeight;
var topVal = $("#markers").children().css('top');
var topValNumber = parseFloat(topVal);
var topRatio = topValNumber / myHeight;
var topValPos;
var scaleRatio;
if (myWidth > myHeight){
scaleRatio = 20/myWidth;
} else {
scaleRatio = 20/myHeight;
}
window.onresize = function() {
sizeMarkers();
}
function init()
{
sizeMarkers();
}
function sizeMarkers()
{
if( typeof( window.innerWidth ) == 'number' ) {
//Non-IE
myWidth = window.innerWidth;
myHeight = window.innerHeight;
} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
//IE 6+ in 'standards compliant mode'
myWidth = document.documentElement.clientWidth;
myHeight = document.documentElement.clientHeight;
} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
//IE 4 compatible
myWidth = document.body.clientWidth;
myHeight = document.body.clientHeight;
}
topVal = $("#markers").children().css('top');
topValNumber = parseFloat(topVal);
topValPos = topRatio * myHeight;
leftVal = $("#markers").children().css('top');
leftValNumber = parseFloat(leftVal);
leftValPos = leftRatio * myWidth;
if (myWidth < myHeight){
$("#markers").children().width(myWidth*scaleRatio);
$("#markers").children().height(myWidth*scaleRatio);
} else {
$("#markers").children().width(myHeight*scaleRatio);
$("#markers").children().height(myHeight*scaleRatio);
}
$("#markers").children().css('top',topValPos);
$("#markers").children().css('left',leftValPos);
$("#infoDiv").html( 'Width = ' + myWidth + ' | Height = ' + myHeight + ' | Top Value: ' + topValPos + ' | Left Value: ' + leftValPos);
}
init();
});
</script>
You could adjust width of your marker using JavaScript by keeping at any onresize events the same ratio marker-width and page-width.
To know your viewport width :
http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
Hope it helps.

Resources