I am making an interactive world map in HTML5. I am using KineticJS to create the polygons of the countries, I currently have Australia and New Zealand. However I want it so if the mouse is over either Australia or New Zealand, they both will be highlighted. I don't know how to use Groups in KineticJS but this is how I tried (i used ellipses for the points because there are a lot of coordinates):
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
#container {
background-image: url('world_map.png');
width: 1026px;
height: 540px;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.2.min.js"> </script>
<script defer="defer">
var stage = new Kinetic.Stage({
container: 'container',
width: 1026,
height: 540
});
var layer = new Kinetic.Layer();
var nznorth = new Kinetic.Polygon({
points: [...],
fill: '#ffffff',
stroke: 'black',
strokeWidth: 1
});
var nzsouth = new Kinetic.Polygon({
points: [...],
fill: '#ffffff',
stroke: 'black',
strokeWidth: 1
});
var ausmain = new Kinetic.Polygon({
points: [...],
fill: '#ffffff',
stroke: 'black',
strokeWidth: 1
});
var aus = new Kinetic.Group();
aus.add(ausmain);
aus.add(nznorth);
aus.add(nzsouth);
aus.on('mouseover', function() {
this.setFill('blue');
layer.draw();
});
aus.on('mouseout', function() {
this.setFill('#ffffff');
layer.draw();
});
layer.add(aus);
stage.add(layer);
</script>
</body>
</html>
How should I implement the group in KineticJS?
You just about have it !
When you handle your mouse events, set the fill on both Australia and New Zealand—not on the group.
group.on("mouseover",function(){
australia.setFill("blue");
newzealand.setFill("blue");
layer.draw();
console.log("over");
});
group.on("mouseout",function(){
australia.setFill("skyblue");
newzealand.setFill("skyblue");
layer.draw();
console.log("out");
});
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/LXvkg/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.1.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 400,
height: 400
});
var layer = new Kinetic.Layer();
stage.add(layer);
stage.draw();
var group=new Kinetic.Group();
layer.add(group);
var australia = new Kinetic.Rect({
x: 20,
y: 20,
width: 150,
height: 100,
fill: "skyblue",
stroke: "lightgray",
strokeWidth: 3
});
group.add(australia);
var newzealand = new Kinetic.Rect({
x: 250,
y: 110,
width: 20,
height: 50,
fill: "skyblue",
stroke: "lightgray",
strokeWidth: 3
});
group.add(newzealand);
layer.draw();
group.on("mouseover",function(){
australia.setFill("blue");
newzealand.setFill("blue");
layer.draw();
console.log("over");
});
group.on("mouseout",function(){
australia.setFill("skyblue");
newzealand.setFill("skyblue");
layer.draw();
console.log("out");
});
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
This tutorial should help you to implement Kinetic groups.
http://www.html5canvastutorials.com/kineticjs/html5-canvas-complex-shapes-using-groups-with-kineticjs/
Related
I want hide and show a Konva.text when I drag a rect -> show text and drag end hide the text but I can't understand why when I drag end the Konva.text do not hide.
var stage = new Konva.Stage({ container: 'container', width: 400, height: 250 });
var layer2 = new Konva.Layer(); var groupe = new Konva.Group({})
var lineV = new Konva.Rect({ x: 50, y: 50, width: 70, height: 50, draggable: true, stroke: 'black'}); groupe.add(lineV)
var info = new Konva.Text({
text: 'info',
visible: false,
stroke: '#fff', fontSize: 35, fontFamily: 'Calibri', fill: '#000', align: 'center', name: "infoBulle"});
layer2.add(info);
groupe.on('dragstart', function () {
console.log("drag")
info.visible(true);
});
groupe.on('dragend', function () {
console.log("drop");
info.visible(false)
console.log(info.isVisible());
});
stage.add(layer2.add(groupe))
stage.draw();
<script src="https://unpkg.com/konva#2.4.2/konva.min.js"></script>
<div id="container" width="400" height="250" style="border: 2px solid red;"></div>
You need to redraw a layer every time you update something on it. The first time you show the text update is visible, because Konva updates layer automatically on dragmove action.
var stage = new Konva.Stage({ container: 'container', width: 400, height: 250 });
var layer2 = new Konva.Layer(); var groupe = new Konva.Group({})
var lineV = new Konva.Rect({ x: 50, y: 50, width: 70, height: 50, draggable: true, stroke: 'black'}); groupe.add(lineV)
var info = new Konva.Text({
text: 'info',
visible: false,
stroke: '#fff', fontSize: 35, fontFamily: 'Calibri', fill: '#000', align: 'center', name: "infoBulle"});
layer2.add(info);
groupe.on('dragstart', function () {
console.log("drag")
info.visible(true);
layer2.batchDraw();
});
groupe.on('dragend', function () {
console.log("drop");
info.visible(false)
layer2.batchDraw();
console.log(info.isVisible());
});
stage.add(layer2.add(groupe))
stage.draw();
<script src="https://unpkg.com/konva#2.4.2/konva.min.js"></script>
<div id="container" width="400" height="250" style="border: 2px solid red;"></div>
<html>
<head>
<style type="text/css">
canvas{
border:1px solid #ccc;
}
.canvas-container{
float: left;
left: 20px;
}
</style>
</head>
<body>
<canvas id='canvas' width='500' height='600' ></canvas>
<canvas id='C2' width='500' height='600'></canvas>
<script type="text/javascript" src="fabric.js"></script>
<script>
(function() {
var canvas = this.__canvas = new fabric.Canvas('canvas');
fabric.Object.prototype.transparentCorners = false;
var radius = 300;
fabric.Image.fromURL('./images/Chrysanthemum.jpg', function(img) {
img.scale(0.4).set({
left: 10,
top: 100,
angle: 0,
clipTo: function (ctx) {
ctx.rect(-250, -250, 400, 400);
}
});
canvas.add(img).setActiveObject(img);
console.log(canvas.getActiveObject());
});
})();
</script>
</body>
----------
</html>
//the code above;
Now the active object size is the same as the image which has not been cropped;
But if there is any way to make the cropped image to be selected.Means the smaller size which will be selected in a smaller size.
thx!
Clip is not meant for that effect:
If you desire some cropping better go with pattern trick if your cropping differs from what the attribute preserverveAspectRatio allows you.
(basically crop in center, crop left crop right, both for x and y axis).
As you see instead of image i create a rect with desired dimensions, then i use the img loaded to create a pattern that will fill the rect.
You can then use offsetX and offsetY on pattern to modify the part of image visible.
offsets are accessible trought:
rect.fill.offsetX
rect.fill.offsetY
(function() {
var canvas = this.__canvas = new fabric.Canvas('canvas');
fabric.Object.prototype.transparentCorners = false;
var radius = 300;
fabric.Image.fromURL('http://fabricjs.com/assets/pug.jpg', function(img) {
var rect = new fabric.Rect({width: 400, height: 400});
var pattern = new fabric.Pattern({source: img.getElement(), offsetX: -20, offsetY: -50});
rect.scale(0.4).set({
left: 10,
top: 100,
angle: 0,
fill: pattern,
});
canvas.add(rect).setActiveObject(rect);
});
})();
canvas{
border:1px solid #ccc;
}
.canvas-container{
float: left;
left: 20px;
}
<canvas id='canvas' width='500' height='600' ></canvas>
<canvas id='C2' width='500' height='600'></canvas>
<script type="text/javascript" src="http://fabricjs.com/lib/fabric.js"></script>
I am plotting the markers on google map using infobox.js not using https://developers.google.com/maps/documentation/javascript/examples/infowindow-simple which is working fine the code is as shown below
<!DOCTYPE html>
<html>
<head lang="en">
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/src/infobox.js"></script>
<style>
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
</style>
<script>
var map;
var AutoCircle = [
{
"latitude": '21.170931',
"longitude": '72.855607',
},
{
"latitude": '21.192533',
"longitude": '72.848750',
},
{
"latitude": '21.190178',
"longitude": '72.797578',
}
];
function initMap() {
// Create the map.
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: {lat:21.181272, lng:72.835066},
mapTypeId: google.maps.MapTypeId.TERRAIN
});
addLabel(AutoCircle);
}
// Construct the circle for each value in citymap.
// Note: We scale the area of the circle based on the population.
function addLabel(circleArray){
for (var i=0;i<circleArray.length;i++) {
var circleData = circleArray[i]
var circleLatlng = new google.maps.LatLng(circleData.latitude, circleData.longitude);
// Add the circle for this city to the map.
var myOptions = {
content: 300+"*"+"<br>autos",
boxStyle: {
background: '#FFFFFF',
color: 'red',
textAlign: "center",
fontSize: "8pt",
width: "50px"
},
disableAutoPan: true,
pixelOffset: new google.maps.Size(-25, -10), // left upper corner of the label
position: new google.maps.LatLng(circleArray[i].latitude,
circleArray[i].longitude),
closeBoxURL: "",
isHidden: false,
pane: "floatPane",
zIndex: 100,
enableEventPropagation: true
};
var ib = new InfoBox(myOptions);
ib.open(map);
}
}
google.maps.event.addDomListener(window, "load", initMap);
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
how to add the infowindow which we click on the label
Please help
I couldn't make it work with a dynamically rendered div from a text string (if you use the domready event, you should be able to access the node by its id, not sure why that doesn't work), If I create the <div> as a DOM node, I can add a listener to it.
code snippet:
function addLabel(circleArray) {
for (var i = 0; i < circleArray.length; i++) {
var circleData = circleArray[i]
var circleLatlng = new google.maps.LatLng(circleData.latitude, circleData.longitude);
// Create div for infoBubble
var div = document.createElement("div");
// create text node
var text = document.createTextNode(300 + "*" + "\nautos\n" + circleData.content);
// append text to div
div.appendChild(text);
// add click listener to div
google.maps.event.addDomListener(div, 'click', (function(i, latLng) {
return function() {
infowindow.setContent('clicked on ' + i);
infowindow.setPosition(latLng);
infowindow.open(map);
}
}(i, circleLatlng)));
var myOptions = {
content: div, // use DOM node for content
boxStyle: {
background: '#FFFFFF',
color: 'red',
textAlign: "center",
fontSize: "8pt",
width: "50px"
},
disableAutoPan: true,
pixelOffset: new google.maps.Size(-25, -10), // left upper corner of the label
position: new google.maps.LatLng(circleArray[i].latitude,
circleArray[i].longitude),
closeBoxURL: "",
isHidden: false,
pane: "floatPane",
zIndex: 100,
enableEventPropagation: true
};
var ib = new InfoBox(myOptions);
ib.open(map);
}
}
var map;
var infowindow = new google.maps.InfoWindow();
function initMap() {
// Create the map.
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: {
lat: 21.181272,
lng: 72.835066
},
mapTypeId: google.maps.MapTypeId.TERRAIN
});
addLabel(AutoCircle);
}
google.maps.event.addDomListener(window, "load", initMap);
var AutoCircle = [{
"latitude": '21.170931',
"longitude": '72.855607',
"content": "content0"
}, {
"latitude": '21.192533',
"longitude": '72.848750',
"content": "content1"
}, {
"latitude": '21.190178',
"longitude": '72.797578',
"content": "content2"
}];
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry,places&ext=.js"></script>
<script src="https://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/src/infobox.js"></script>
<div id="map"></div>
If I understand your code correctly, the 'label' you refer to is an instance of the InfoBox class, which according to its docs, "fires the same events as a google.maps.InfoWindow":
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/reference.html
So you should be able to do something like:
var infowindow = new google.maps.InfoWindow({
content: 'foo'
});
ib.addListener('click', function() {
infowindow.open(map, this);
});
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.
I have prepared a simplified test case and a screenshot.
I think I'm missing a tiny bit, just few lines of code.
I have 2 overlays (the weather and clouds) in my JavaScript Google Map and would like to hide or show them when a corresponding check box is clicked:
Here is the test case, just paste it into an .html file and it will run:
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
h1,p {
text-align: center;
}
#map {
width: 700px;
height: 400px;
margin-left: auto;
margin-right: auto;
background-color: #CCCCFF;
}
</style>
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false&language=de&libraries=weather"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
findCity('Berlin');
$('#weather_box,#clouds_box').click(function(){
alert('How to hide/show layers? Checked: ' + $(this).is(':checked'));
});
});
function createMap(center) {
var opts = {
zoom: 6,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
return new google.maps.Map(document.getElementById('map'), opts);
}
function findCity(city) {
var gc = new google.maps.Geocoder();
gc.geocode({address: city}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var pos = results[0].geometry.location;
var map = createMap(pos);
var marker = new google.maps.Marker({
map: map,
title: city,
position: pos,
animation: google.maps.Animation.DROP
});
var weatherLayer = new google.maps.weather.WeatherLayer({
temperatureUnits: google.maps.weather.TemperatureUnit.CELSIUS
});
weatherLayer.setMap(map);
//var cloudLayer = new google.maps.weather.CloudLayer();
//cloudLayer.setMap(map);
}
});
}
</script>
</head>
<body>
<h1>Berlin</h1>
<p>Show:
<label><input type="checkbox" id="weather_box" checked>weather</label>
<label><input type="checkbox" id="clouds_box">clouds</label>
</p>
<div id="map"></div>
</body>
</html>
UPDATE: Thanks, here a working version for everyone
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
h1,p {
text-align: center;
}
#map {
width: 700px;
height: 400px;
margin-left: auto;
margin-right: auto;
background-color: #CCCCFF;
}
</style>
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false&language=de&libraries=weather"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
var map;
var WeatherLayer;
var CloudsLayer;
$(function() {
findCity('Berlin');
});
function createMap(center) {
var opts = {
zoom: 6,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
return new google.maps.Map(document.getElementById('map'), opts);
}
function findCity(city) {
var gc = new google.maps.Geocoder();
gc.geocode({address: city}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var pos = results[0].geometry.location;
map = createMap(pos);
var marker = new google.maps.Marker({
map: map,
title: city,
position: pos,
animation: google.maps.Animation.DROP
});
weatherLayer = new google.maps.weather.WeatherLayer({
temperatureUnits: google.maps.weather.TemperatureUnit.CELSIUS
});
weatherLayer.setMap(map);
cloudsLayer = new google.maps.weather.CloudLayer();
//cloudsLayer.setMap(map);
$('#weather_box').click(function(){
weatherLayer.setMap($(this).is(':checked') ? map : null);
});
$('#clouds_box').click(function(){
cloudsLayer.setMap($(this).is(':checked') ? map : null);
});
$('#weather_box,#clouds_box').removeAttr('disabled');
}
});
}
</script>
</head>
<body>
<h1>Berlin</h1>
<p>Show:
<label><input type="checkbox" id="weather_box" disabled="true" checked>weather</label>
<label><input type="checkbox" id="clouds_box" disabled="true">clouds</label>
</p>
<div id="map"></div>
</body>
</html>
You can hide/show the layer with setMap method:
if ($(this).is(':checked'))
weatherLayer.setMap(map); // show
else
weatherLayer.setMap(null); // hide
See working example: http://jsfiddle.net/EeVUr/2/ (removed your second checkbox, as you have only one layer now. But you can easily create two different layers and switch them.)
If you use deckgl along with deckgl, set the visible property to true or false.
and in updateTriggers, keep the variable that decides the visibility
eg:
new GeoJsonLayer({
...otherProps,
updateTriggers: {
visible: [decisionVariable],
}
visible: decisionVariable ? true : false,
})