I want to restrict the area that an image can be drawn on a canvas. I am using Fabric.js.
I tried the following link, but it didn't work for me. Set object drag limit in Fabric.js.
I want any part of the image that would be drawn outside the red rectangle (pictured below) to just not be drawn.
var canvas = new fabric.Canvas('canvas');
$("#canvascolor > input").click(function() {
canvas.setBackgroundImage(this.src, canvas.renderAll.bind(canvas), {
crossOrigin: 'anonymous'
});
});
// trigger the first one at startup
$("#canvascolor > input:first-of-type()")[0].click();
document.getElementById('file').addEventListener("change", function(e) {
var file = e.target.files[0];
var reader = new FileReader();
console.log("reader " + reader);
reader.onload = function(f) {
var data = f.target.result;
fabric.Image.fromURL(data, function(img) {
var oImg = img.set({
left: 140,
top: 100,
width: 250,
height: 200,
angle: 0
}).scale(0.9);
oImg.lockMovementX = true;
canvas.add(oImg).renderAll();
var a = canvas.setActiveObject(oImg);
var dataURL = canvas.toDataURL({
format: 'png',
quality: 0.8
});
});
};
reader.readAsDataURL(file);
});
document.querySelector('#txt').onclick = function(e) {
e.preventDefault();
canvas.deactivateAll().renderAll();
document.querySelector('#preview').src = canvas.toDataURL();
};
canvas {
border: 1px solid black;
}
#canvascolor input {
height: 50px;
width: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.min.js"></script>
<input type="file" id="file">
<canvas id="canvas" width="520" height="520"></canvas>
<section id="canvascolor">
<input class="canvasborder" type="image" src="https://dl.dropboxusercontent.com/s/9leyl96qd3tytn8/tshirt-front.jpg">
<input class="canvasborder" type="image" src="https://dl.dropboxusercontent.com/s/tk0fs5v4muo6898/tshirt-back.jpg">
</section>
<button href='' id='txt' target="_blank">submit</button><br/>
<img id="preview" />
I extended your script to answer you.
For your use case it looks like you could use some clipping function and uniform centered scaling.
Anyway the main question about restricting area for drawing is this:
var canvas = new fabric.Canvas('canvas');
$("#canvascolor > input").click(function() {
canvas.setBackgroundImage(this.src, canvas.renderAll.bind(canvas), {
crossOrigin: 'anonymous'
});
});
// trigger the first one at startup
$("#canvascolor > input:first-of-type()")[0].click();
function clipTShirt(ctx) {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
var x = 140, y = 100 ,w = 225, h = 300;
ctx.moveTo(x, y);
ctx.lineTo(x + w, y);
ctx.lineTo(x + w, y + h);
ctx.lineTo(x, y + h);
ctx.lineTo(x, y);
ctx.restore();
}
document.getElementById('file').addEventListener("change", function(e) {
var file = e.target.files[0];
var reader = new FileReader();
console.log("reader " + reader);
reader.onload = function(f) {
var data = f.target.result;
fabric.Image.fromURL(data, function(img) {
var oImg = img.set({
left: 140,
top: 100,
width: 250,
height: 200,
angle: 0,
lockUniScaling: true,
centeredScaling: true,
clipTo: clipTShirt
}).scale(0.9);
oImg.lockMovementX = true;
canvas.add(oImg).renderAll();
var a = canvas.setActiveObject(oImg);
var dataURL = canvas.toDataURL({
format: 'png',
quality: 0.8
});
});
};
reader.readAsDataURL(file);
});
document.querySelector('#txt').onclick = function(e) {
e.preventDefault();
canvas.deactivateAll().renderAll();
document.querySelector('#preview').src = canvas.toDataURL();
};
canvas {
border: 1px solid black;
}
#canvascolor input {
height: 50px;
width: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.min.js"></script>
<input type="file" id="file">
<canvas id="canvas" width="520" height="520"></canvas>
<section id="canvascolor">
<input class="canvasborder" type="image" src="https://dl.dropboxusercontent.com/s/9leyl96qd3tytn8/tshirt-front.jpg">
<input class="canvasborder" type="image" src="https://dl.dropboxusercontent.com/s/tk0fs5v4muo6898/tshirt-back.jpg">
</section>
<button href='' id='txt' target="_blank">submit</button><br/>
<img id="preview" />
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 10 months ago.
The community is reviewing whether to reopen this question as of 9 months ago.
Improve this question
strong text
body {
margin: 0;
height: 100vh;
}
canvas {
display: block;
}
h1 {
position: absolute;
top: 8em;
left: 8em;
font-family: 'Serif';
font-size: 7em;
text-transform: uppercase;
width: auto;
line-height: .8em;
border: 5px solid black;
padding: .2em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
**Below is the Home Page button I am trying to create**
**I know that is just a Header tag and not a button. I know how to make a button but my main problem is positioning**
**Nomatter what I do, the positioning is always at the very top of the page. My goal is to get it smack dab in the middle, over the graphic animations.**
<h1> Enter Home Page</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.2/TweenMax.min.js"></script>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.z = 5;
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor("#e5e5e5");
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
})
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshLambertMaterial({
color: 0xF7F7F7
});
//var mesh = new THREE.Mesh(geometry, material);
//scene.add(mesh);
meshX = -10;
for (var i = 0; i < 15; i++) {
var mesh = new THREE.Mesh(geometry, material);
mesh.position.x = (Math.random() - 0.5) * 10;
mesh.position.y = (Math.random() - 0.5) * 10;
mesh.position.z = (Math.random() - 0.5) * 10;
scene.add(mesh);
meshX += 1;
}
var light = new THREE.PointLight(0xFFFFFF, 1, 1000)
light.position.set(0, 0, 0);
scene.add(light);
var light = new THREE.PointLight(0xFFFFFF, 2, 1000)
light.position.set(0, 0, 25);
scene.add(light);
var render = function() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function onMouseMove(event) {
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children, true);
for (var i = 0; i < intersects.length; i++) {
this.tl = new TimelineMax();
this.tl.to(intersects[i].object.scale, 1, {
x: 2,
ease: Expo.easeOut
})
this.tl.to(intersects[i].object.scale, .5, {
x: .5,
ease: Expo.easeOut
})
this.tl.to(intersects[i].object.position, .5, {
x: 2,
ease: Expo.easeOut
})
this.tl.to(intersects[i].object.rotation, .5, {
y: Math.PI * .5,
ease: Expo.easeOut
}, "=-1.5")
}
}
window.addEventListener('mousemove', onMouseMove);
render();
</script>
</body>
</html>
First of all I suggest you to better understand how a good question is built. I don't know if my answer is correct, but the formatting of a question is important to get a good answer.
Anyway, I hope this is what you were looking for. I created a fixed container which fill the whole viewport and with display: flex I centered the content with align-items and justify-content.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.z = 5;
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor("#e5e5e5");
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
})
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshLambertMaterial({
color: 0xF7F7F7
});
//var mesh = new THREE.Mesh(geometry, material);
//scene.add(mesh);
meshX = -10;
for (var i = 0; i < 15; i++) {
var mesh = new THREE.Mesh(geometry, material);
mesh.position.x = (Math.random() - 0.5) * 10;
mesh.position.y = (Math.random() - 0.5) * 10;
mesh.position.z = (Math.random() - 0.5) * 10;
scene.add(mesh);
meshX += 1;
}
var light = new THREE.PointLight(0xFFFFFF, 1, 1000)
light.position.set(0, 0, 0);
scene.add(light);
var light = new THREE.PointLight(0xFFFFFF, 2, 1000)
light.position.set(0, 0, 25);
scene.add(light);
var render = function() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function onMouseMove(event) {
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children, true);
for (var i = 0; i < intersects.length; i++) {
this.tl = new TimelineMax();
this.tl.to(intersects[i].object.scale, 1, {
x: 2,
ease: Expo.easeOut
})
this.tl.to(intersects[i].object.scale, .5, {
x: .5,
ease: Expo.easeOut
})
this.tl.to(intersects[i].object.position, .5, {
x: 2,
ease: Expo.easeOut
})
this.tl.to(intersects[i].object.rotation, .5, {
y: Math.PI * .5,
ease: Expo.easeOut
}, "=-1.5")
}
}
window.addEventListener('mousemove', onMouseMove);
render();
body {
margin: 0;
height: 100vh;
}
canvas {
display: block;
}
.center {
position: fixed;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
display: flex;
align-items: center;
justify-content: center;
}
.center h1 {
display: inline;
width: auto;
line-height: .8em;
font-family: 'Serif';
font-size: 2em;
text-transform: uppercase;
border: 5px solid black;
padding: .2em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.2/TweenMax.min.js"></script>
<div class="center">
<h1> Enter Home Page</h1>
</div>
How to make Zooming effect like these, when hovering the image Sample Image
$(document).ready(function(){
var native_width = 0;
var native_height = 0;
//Now the mousemove function
$(".magnify").mousemove(function(e){
//When the user hovers on the image, the script will first calculate
//the native dimensions if they don't exist. Only after the native dimensions
//are available, the script will show the zoomed version.
if(!native_width && !native_height)
{
//This will create a new image object with the same image as that in .small
//We cannot directly get the dimensions from .small because of the
//width specified to 200px in the html. To get the actual dimensions we have
//created this image object.
var image_object = new Image();
image_object.src = $(".small").attr("src");
//This code is wrapped in the .load function which is important.
//width and height of the object would return 0 if accessed before
//the image gets loaded.
native_width = image_object.width;
native_height = image_object.height;
}
else
{
//x/y coordinates of the mouse
//This is the position of .magnify with respect to the document.
var magnify_offset = $(this).offset();
//We will deduct the positions of .magnify from the mouse positions with
//respect to the document to get the mouse positions with respect to the
//container(.magnify)
var mx = e.pageX - magnify_offset.left;
var my = e.pageY - magnify_offset.top;
//Finally the code to fade out the glass if the mouse is outside the container
if(mx < $(this).width() && my < $(this).height() && mx > 0 && my > 0)
{
$(".large").fadeIn(100);
}
else
{
$(".large").fadeOut(100);
}
if($(".large").is(":visible"))
{
//The background position of .large will be changed according to the position
//of the mouse over the .small image. So we will get the ratio of the pixel
//under the mouse pointer with respect to the image and use that to position the
//large image inside the magnifying glass
var rx = Math.round(mx/$(".small").width()*native_width - $(".large").width()/2)*-1;
var ry = Math.round(my/$(".small").height()*native_height - $(".large").height()/2)*-1;
var bgp = rx + "px " + ry + "px";
//Time to move the magnifying glass with the mouse
var px = mx - $(".large").width()/2;
var py = my - $(".large").height()/2;
//Now the glass moves with the mouse
//The logic is to deduct half of the glass's width and height from the
//mouse coordinates to place it with its center at the mouse coordinates
//If you hover on the image now, you should see the magnifying glass in action
$(".large").css({left: px, top: py, backgroundPosition: bgp});
}
}
})
})
/*Some CSS*/
* {margin: 0; padding: 0;}
.magnify {width: 200px; margin: 50px auto; position: relative;}
/*Lets create the magnifying glass*/
.large {
width: 175px; height: 175px;
position: absolute;
border-radius: 100%;
/*Multiple box shadows to achieve the glass effect*/
box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.85),
0 0 7px 7px rgba(0, 0, 0, 0.25),
inset 0 0 40px 2px rgba(0, 0, 0, 0.25);
/*Lets load up the large image first*/
background: url('http://thecodeplayer.com/uploads/media/iphone.jpg') no-repeat;
/*hide the glass by default*/
display: none;
}
/*To solve overlap bug at the edges during magnification*/
.small { display: block; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Lets make a simple image magnifier -->
<div class="magnify">
<!-- This is the magnifying glass which will contain the original/large version -->
<div class="large"></div>
<!-- This is the small image -->
<img class="small" src="http://thecodeplayer.com/uploads/media/iphone.jpg" width="200"/>
</div>
<!-- Lets load up prefixfree to handle CSS3 vendor prefixes -->
<script src="http://thecodeplayer.com/uploads/js/prefixfree.js" type="text/javascript"></script>
<!-- You can download it from http://leaverou.github.com/prefixfree/ -->
<!-- Time for jquery action -->
<script src="http://thecodeplayer.com/uploads/js/jquery-1.7.1.min.js" type="text/javascript"></script>
Try this one
(function ($) {
$(document).ready(function() {
$('.xzoom, .xzoom-gallery').xzoom({zoomWidth: 400, title: true, tint: '#333', Xoffset: 15});
$('.xzoom2, .xzoom-gallery2').xzoom({position: '#xzoom2-id', tint: '#ffa200'});
$('.xzoom3, .xzoom-gallery3').xzoom({position: 'lens', lensShape: 'circle', sourceClass: 'xzoom-hidden'});
$('.xzoom4, .xzoom-gallery4').xzoom({tint: '#006699', Xoffset: 15});
$('.xzoom5, .xzoom-gallery5').xzoom({tint: '#006699', Xoffset: 15});
//Integration with hammer.js
var isTouchSupported = 'ontouchstart' in window;
if (isTouchSupported) {
//If touch device
$('.xzoom, .xzoom2, .xzoom3, .xzoom4, .xzoom5').each(function(){
var xzoom = $(this).data('xzoom');
xzoom.eventunbind();
});
$('.xzoom, .xzoom2, .xzoom3').each(function() {
var xzoom = $(this).data('xzoom');
$(this).hammer().on("tap", function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
var s = 1, ls;
xzoom.eventmove = function(element) {
element.hammer().on('drag', function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
xzoom.movezoom(event);
event.gesture.preventDefault();
});
}
xzoom.eventleave = function(element) {
element.hammer().on('tap', function(event) {
xzoom.closezoom();
});
}
xzoom.openzoom(event);
});
});
$('.xzoom4').each(function() {
var xzoom = $(this).data('xzoom');
$(this).hammer().on("tap", function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
var s = 1, ls;
xzoom.eventmove = function(element) {
element.hammer().on('drag', function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
xzoom.movezoom(event);
event.gesture.preventDefault();
});
}
var counter = 0;
xzoom.eventclick = function(element) {
element.hammer().on('tap', function() {
counter++;
if (counter == 1) setTimeout(openfancy,300);
event.gesture.preventDefault();
});
}
function openfancy() {
if (counter == 2) {
xzoom.closezoom();
$.fancybox.open(xzoom.gallery().cgallery);
} else {
xzoom.closezoom();
}
counter = 0;
}
xzoom.openzoom(event);
});
});
$('.xzoom5').each(function() {
var xzoom = $(this).data('xzoom');
$(this).hammer().on("tap", function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
var s = 1, ls;
xzoom.eventmove = function(element) {
element.hammer().on('drag', function(event) {
event.pageX = event.gesture.center.pageX;
event.pageY = event.gesture.center.pageY;
xzoom.movezoom(event);
event.gesture.preventDefault();
});
}
var counter = 0;
xzoom.eventclick = function(element) {
element.hammer().on('tap', function() {
counter++;
if (counter == 1) setTimeout(openmagnific,300);
event.gesture.preventDefault();
});
}
function openmagnific() {
if (counter == 2) {
xzoom.closezoom();
var gallery = xzoom.gallery().cgallery;
var i, images = new Array();
for (i in gallery) {
images[i] = {src: gallery[i]};
}
$.magnificPopup.open({items: images, type:'image', gallery: {enabled: true}});
} else {
xzoom.closezoom();
}
counter = 0;
}
xzoom.openzoom(event);
});
});
} else {
//If not touch device
//Integration with fancybox plugin
$('#xzoom-fancy').bind('click', function(event) {
var xzoom = $(this).data('xzoom');
xzoom.closezoom();
$.fancybox.open(xzoom.gallery().cgallery, {padding: 0, helpers: {overlay: {locked: false}}});
event.preventDefault();
});
//Integration with magnific popup plugin
$('#xzoom-magnific').bind('click', function(event) {
var xzoom = $(this).data('xzoom');
xzoom.closezoom();
var gallery = xzoom.gallery().cgallery;
var i, images = new Array();
for (i in gallery) {
images[i] = {src: gallery[i]};
}
$.magnificPopup.open({items: images, type:'image', gallery: {enabled: true}});
event.preventDefault();
});
}
});
})(jQuery);
<link href="https://unpkg.com/xzoom#1.0.7/dist/xzoom.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-2.1.1.js"></script>
<script src="https://unpkg.com/xzoom#1.0.7/dist/xzoom.min.js"></script>
<script src="https://hammerjs.github.io/dist/hammer.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/js/foundation.min.js"></script>
<body>
<div class="container">
<!-- default start -->
<section id="default" class="padding-top0">
<div class="row">
<div class="large-12 column"><h3>Product Zooming</h3></div>
<hr>
<div class="large-5 column">
<div class="xzoom-container">
<img class="xzoom" id="xzoom-default" src="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/preview/01_b_car.jpg" xoriginal="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/original/01_b_car.jpg" />
<div class="xzoom-thumbs">
<img class="xzoom-gallery" width="80" src="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/thumbs/01_b_car.jpg" xpreview="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/preview/01_b_car.jpg" title="The description goes here">
<img class="xzoom-gallery" width="80" src="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/preview/02_o_car.jpg" title="The description goes here">
<img class="xzoom-gallery" width="80" src="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/preview/03_r_car.jpg" title="The description goes here">
<img class="xzoom-gallery" width="80" src="http://www.jqueryscript.net/demo/Feature-rich-Product-Gallery-With-Image-Zoom-xZoom/images/gallery/preview/04_g_car.jpg" title="The description goes here">
</div>
</div>
</div>
<div class="large-7 column"></div>
</div>
</section>
<!-- default end -->
</div>
</body>
I've seen some cool image masking and other effects with CSS3. Using only CSS3 can we achieve this effect seen in the code below or see working fiddle.
http://jsfiddle.net/s6u9a/
HTML
<canvas id="canvas1" width="400" height="400"></canvas>
Javascript
var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');
can.addEventListener('mousemove', function(e) {
var mouse = getMouse(e, can);
redraw(mouse);
}, false);
function redraw(mouse) {
console.log('a');
can.width = can.width;
ctx.drawImage(img, 0, 0);
ctx.beginPath();
ctx.rect(0,0,500,500);
ctx.arc(mouse.x, mouse.y, 70, 0, Math.PI*2, true)
ctx.clip();
ctx.drawImage(img2, 0, 0);
}
var img = new Image();
img.onload = function() {
redraw({x: -450, y: -500})
}
img.src = 'http://placekitten.com/400/400';
var img2 = new Image();
img2.onload = function() {
redraw({x: -450, y: -500})
}
img2.src = 'http://placekitten.com/400/395';
function getMouse(e, canvas) {
var element = canvas,
offsetX = 0,
offsetY = 0,
mx, my;
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
return {
x: mx,
y: my
};
}
Here's an alternate approach using background-image. It's more flexible, and you get a circular (or arbitrarily shaped) viewport:
http://jsfiddle.net/maackle/66uCs/
HTML
<div class="masker">
<img class="base" src="http://lorempixel.com/400/400/cats/1" />
<div class="overlay"></div>
</div>
CSS
.masker {
position: relative;
}
.overlay {
position: absolute;
display: none;
width: 100px;
height: 100px;
border-radius: 50%;
background: url(http://lorempixel.com/400/400/cats/2) no-repeat;
}
jQuery 1.10.1
$('.masker').on('mousemove', function (e) {
var r, x, y, top, left, bottom, right, attr, $base, $overlay;
r = 100;
$base = $(this).find('.base');
$overlay = $(this).find('.overlay');
x = e.pageX - $base.offset().left;
y = e.pageY - $base.offset().top;
top = y - r / 2;
left = x - r / 2;
if (x < 0 || y < 0 || x > $base.width() || y > $base.height()) {
$overlay.hide();
} else {
$overlay.show().css({
'background-position': '' + (-left) + 'px ' + (-top) + 'px',
'left': left,
'top': top
});
}
});
//just for good measure
$('.masker').on('mouseout', function (e) {
$(this).find('.overlay').hide();
});
Here's a solution that uses mostly CSS -- you do need some Javascript to detect the mouse position. Note that this gives you a square viewport instead of a circle, but if CSS ever adds circle() alongside rect() for the clip property, you will have that option:
http://jsfiddle.net/maackle/Yc2b4/
HTML
<div class="masker">
<img class="base" src="http://lorempixel.com/400/400/cats/1" />
<img class="overlay" src="http://lorempixel.com/400/400/cats/2" />
</div>
CSS
.masker {
position: relative;
}
.overlay {
position: absolute;
top: 0;
left: 0;
display: none;
}
jQuery 1.10.1
$('.masker img').on('mousemove', function(e) {
var r, x, y, top, left, bottom, right, attr, $overlay;
r = 100;
x = e.pageX - $(this).offset().left;
y = e.pageY - $(this).offset().top;
top = y - r/2;
left = x - r/2;
bottom = y + r/2;
right = x + r/2;
attr = 'rect('+(top)+'px, '+(right)+'px, '+(bottom)+'px, '+(left)+'px)';
$overlay = $('.masker .overlay');
$overlay.show().css({clip: attr});
});
$('.masker img').on('mouseout', function(e) {
$('.masker .overlay').hide();
});
I found a script from one of my colleague.
All I want is an autocomplete from Google maps for the locations in United states and Canada. I saw that I cannot add multiple countries in componentRestrictions but, if you know a workaround that would be of great help too.
The Script which I have here is :
<!DOCTYPE html>
<html>
<head>
<title>Google Maps JavaScript API v3 Example: Places Autocomplete</title>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
<style>
body {
font-family: sans-serif;
font-size: 14px;
}
#map_canvas {
height: 400px;
width: 600px;
margin-top: 0.6em;
}
input {
border: 1px solid rgba(0, 0, 0, 0.5);
}
input.notfound {
border: 2px solid rgba(255, 0, 0, 0.4);
}
</style>
<script>
function initialize() {
var input = document.getElementById('searchTextField');
var options = {
types: ['(cities)'],
componentRestrictions: {country: 'us'}
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
function setupClickListener(id, types) {
var radioButton = document.getElementById(id);
google.maps.event.addDomListener(radioButton, 'click', function() {
autocomplete.setTypes(types);
});
}
setupClickListener('changetype-all', []);
setupClickListener('changetype-establishment', ['establishment']);
setupClickListener('changetype-geocode', ['geocode']);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div>
<input id="searchTextField" type="text" size="50">
<input type="radio" name="type" id="changetype-all" checked="checked">
<label for="changetype-all">All</label>
<input type="radio" name="type" id="changetype-establishment">
<label for="changetype-establishment">Establishments</label>
<input type="radio" name="type" id="changetype-geocode">
<label for="changetype-geocode">Geocodes</lable>
</div>
</body>
</html>
This script works! But, the problem is, I do not want radio buttons and when I remove them and relevant script, it stops working completely!
I just want auto complete without anything else around it.
Again, this script is not written by me.
EDIT:
My question is related to https://gis.stackexchange.com/questions/31916/i-am-trying-to-put-autocomplete-of-google-api-v3-for-places-but-giving-some-err
which Google gave me... although even that chap is struggling :(
The multiple countries filter was introduced in version 3.27 of Maps JavaScript API in January 2017:
You can now restrict Autocomplete predictions to only surface from multiple countries. You can do this by specifying up to 5 countries in the componentRestrictions field of the AutocompleteOptions.
https://developers.google.com/maps/documentation/javascript/releases
https://developers.google.com/maps/documentation/javascript/reference#ComponentRestrictions
Have a look at this example: http://jsbin.com/ramagi/edit?html,output
var G = google.maps;
var chicago = new G.LatLng(41.850033, -87.6500523);
var infowindow = new G.InfoWindow();
var marker;
function initialize() {
var mapOptions = {
center: chicago,
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
marker = new G.Marker({map:map});
var input = document.getElementById('searchTextField');
var options = {
types: ['(cities)'],
componentRestrictions: {country: ['us', 'ca']}
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
infowindow.close();
var place = autocomplete.getPlace();
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
var image = new google.maps.MarkerImage(
place.icon,
new google.maps.Size(71, 71),
new google.maps.Point(0, 0),
new google.maps.Point(17, 34),
new google.maps.Size(35, 35));
marker.setIcon(image);
marker.setPosition(place.geometry.location);
var address = '';
if (place.address_components) {
address = [(place.address_components[0] &&
place.address_components[0].short_name || ''),
(place.address_components[1] &&
place.address_components[1].short_name || ''),
(place.address_components[2] &&
place.address_components[2].short_name || '')
].join(' ');
}
infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
infowindow.open(map, marker);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
body {
font-family: sans-serif;
font-size: 14px;
}
#map_canvas {
height: 400px;
width: 600px;
margin-top: 0.6em;
}
input {
border: 1px solid rgba(0, 0, 0, 0.5);
}
input.notfound {
border: 2px solid rgba(255, 0, 0, 0.4);
}
<div>
<input id="searchTextField" type="text" size="50">
<div id="map_canvas"></div>
</div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&libraries=places"></script>
All I had to do was simply remove lines, one by one... I noticed, I removed that extra } until Chrome console told me!
Simple solution.
<!DOCTYPE html>
<html>
<head>
<title>Google Maps JavaScript API v3 Example: Places Autocomplete</title>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
<style>
body {
font-family: sans-serif;
font-size: 14px;
}
#map_canvas {
height: 400px;
width: 600px;
margin-top: 0.6em;
}
input {
border: 1px solid rgba(0, 0, 0, 0.5);
}
input.notfound {
border: 2px solid rgba(255, 0, 0, 0.4);
}
</style>
<script>
function initialize() {
var input = document.getElementById('searchTextField');
var options = {
componentRestrictions: {country: 'us'}
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<form method = "POST">
<div>
<input id="searchTextField" type="text" size="50" name="location">
</div>
<input type = "submit" />
</body>
</html>
Copy + paste service (Live demo here.):
<!DOCTYPE html>
<html>
<head>
<title>Google Maps JavaScript API v3 Example: Places Autocomplete</title>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
<style>
body {
font-family: sans-serif;
font-size: 14px;
}
#map_canvas {
height: 400px;
width: 600px;
margin-top: 0.6em;
}
input {
border: 1px solid rgba(0, 0, 0, 0.5);
}
input.notfound {
border: 2px solid rgba(255, 0, 0, 0.4);
}
</style>
<script>
var G = google.maps;
var chicago = new G.LatLng(41.850033, -87.6500523);
var infowindow = new G.InfoWindow();
var marker;
function initialize() {
var mapOptions = {
center: chicago,
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
marker = new G.Marker({map:map});
var input = document.getElementById('searchTextField');
var options = {
types: ['(cities)'],
componentRestrictions: {country: 'us'}
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
infowindow.close();
var place = autocomplete.getPlace();
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
var image = new google.maps.MarkerImage(
place.icon,
new google.maps.Size(71, 71),
new google.maps.Point(0, 0),
new google.maps.Point(17, 34),
new google.maps.Size(35, 35));
marker.setIcon(image);
marker.setPosition(place.geometry.location);
var address = '';
if (place.address_components) {
address = [(place.address_components[0] &&
place.address_components[0].short_name || ''),
(place.address_components[1] &&
place.address_components[1].short_name || ''),
(place.address_components[2] &&
place.address_components[2].short_name || '')
].join(' ');
}
infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
infowindow.open(map, marker);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div>
<input id="searchTextField" type="text" size="50">
<div id="map_canvas"></div>
</div>
</body>
</html>
If you don't want any radio button, just replace them with , something like this:
<div name="type" id="changetype-all" checked="checked"></div>
<label for="changetype-all">All</label>
<div name="type" id="changetype-establishment"></div>
<label for="changetype-establishment">Establishments</label>
<div name="type" id="changetype-geocode"></div>
<label for="changetype-geocode">Geocodes</lable>
I am using transitionTo method of kineticJS to show animated rotation of a shape on click event of mouse. It works fine if we click the shape first time but then on subsequent clicks it does not rotate the shape. I want to show transition(rotation) of the shape by some angle every time I click on it. Please let me know the mistake I am making and how can I correct it??
This is the code I am using
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
canvas {
border: 1px solid #9C9898;
}
</style>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v3.9.6.js"></script>
<script>
window.onload = function() {
var stage = new Kinetic.Stage({
container: "container",
width: 578,
height: 200
});
var layer = new Kinetic.Layer({
x:stage.getWidth()/3 ,
y: stage.getHeight()/3
});
var rect = new Kinetic.Rect({
x: 239,
y: 75,
width: 100,
height: 50,
fill: "#00D2FF",
stroke: "black",
strokeWidth: 4,
centerOffset: [50, 100]
});
// add the shape to the layer
layer.add(rect);
// add the layer to the stage
stage.add(layer);
rect.on("click", function() {
rect.transitionTo({
rotation:2*Math.PI,
duration:1
});
stage.draw();
});
};
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
Try this:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
canvas {
border: 1px solid #9C9898;
}
</style>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v3.10.0.js"></script>
<script>
window.onload = function() {
var angle = 0;
var stage = new Kinetic.Stage({
container: "container",
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 239,
y: 75,
width: 100,
height: 50,
fill: "#00D2FF",
stroke: "black",
strokeWidth: 4
});
layer.add(rect);
stage.add(layer);
rect.on("click", function() {
angle += 2;
rect.transitionTo({
rotation: Math.PI * angle,
duration:1
});
});
};
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
The click was working just fine, however you were telling it to rotate to the same angel every time (why it only animates on the first click). I added a variable so that the angle increases 360 degrees every time you click on it.