For a digital artwork I'm generating a canvas element in Vue which draws from an array of multiple images.
The images can be split in two categories:
SVG (comes with a fill-color)
PNG (just needs to be drawn as a regular image)
I came up with this:
const depict = (options) => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const myOptions = Object.assign({}, options);
if (myOptions.ext == "svg") {
return loadImage(myOptions.uri).then((img) => {
ctx.drawImage(img, 0, 0, 100, 100);
ctx.globalCompositeOperation = "source-in";
ctx.fillStyle = myOptions.clr;
ctx.fillRect(0, 0, 100, 100);
ctx.globalCompositeOperation = "source-over";
});
} else {
return loadImage(myOptions.uri).then((img) => {
ctx.fillStyle = myOptions.clr;
ctx.drawImage(img, 0, 0, 100, 100);
});
}
};
this.inputs.forEach(depict);
for context:
myOptions.clr = the color
myOptions.uri = the url of the image
myOptions.ext = the extension of the image
While all images are drawn correctly I can't figure out why the last fillStyle overlays the whole image. I just want all the svg's to have the fillStyle which is attached to them.
I tried multiple globalCompositeOperation in different orders. I also tried drawing the svg between ctx.save and ctx.restore. No succes… I might be missing some logic here.
So! I figured it out myself in the meantime :)
I created an async loop with a promise. Inside this I created a temporary canvas per image which I then drew to one canvas. I took inspiration from this solution: https://stackoverflow.com/a/6687218/15289586
Here is the final code:
// create the parent canvas
let parentCanv = document.createElement("canvas");
const getContext = () => parentCanv.getContext("2d");
const parentCtx = getContext();
parentCanv.classList.add("grid");
// det the wrapper from the DOM
let wrapper = document.getElementById("wrapper");
// this function loops through the array
async function drawShapes(files) {
for (const file of files) {
await depict(file);
}
// if looped > append parent canvas to to wrapper
wrapper.appendChild(parentCanv);
}
// async image loading worked best
const loadImage = (url) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`load ${url} fail`));
img.src = url;
});
};
// depict the file
const depict = (options) => {
// make a promise
return new Promise((accept, reject) => {
const myOptions = Object.assign({}, options);
var childCanv = document.createElement("canvas");
const getContext = () => childCanv.getContext("2d");
const childCtx = getContext();
if (myOptions.ext == "svg") {
loadImage(myOptions.uri).then((img) => {
childCtx.drawImage(img, 0, 0, 100, parentCanv.height);
childCtx.globalCompositeOperation = "source-in";
childCtx.fillStyle = myOptions.clr;
childCtx.fillRect(0, 0, parentCanv.width, parentCanv.height);
parentCtx.drawImage(childCanv, 0, 0);
accept();
});
} else {
loadImage(myOptions.uri).then((img) => {
// ctx.fillStyle = myOptions.clr;
childCtx.drawImage(img, 0, 0, 100, parentCanv.height);
parentCtx.drawImage(childCanv, 0, 0);
accept();
});
}
});
};
drawShapes(this.inputs);
Hello everyone,I have meet a strange problem which is that I loaded a gltf model in three.js and set color for it.When zooming in it has colors, but when zooming out,it is all black.And when I directly set color for it's material,it can works well.
Thank you.
here is the sample sreenphotos and code.
loadGlbModel() {
const loader = new GLTFLoader();
loader.load(
`/three/eiffel-tower.gltf`,
(gltf) => {
const geometry = gltf.scene.children[0].geometry;
const positions = geometry.attributes.position;
const count = positions.count;
geometry.setAttribute(
"color",
new THREE.BufferAttribute(new Float32Array(count * 3), 3)
);
const color = new THREE.Color();
const colors = geometry.attributes.color;
const radius = 200;
debugger;
for (let i = 0; i < count; i++) {
color.setHSL(positions.getY(i) / radius / 2, 1.0, 0.5);
colors.setXYZ(i, 1, 0, 0);
}
const material = new THREE.MeshPhongMaterial({
color: 0xffffff,
flatShading: true,
vertexColors: true,
shininess: 0,
});
const wireframeMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true,
transparent: true,
});
let mesh = new THREE.Mesh(geometry, material);
let wireframe = new THREE.Mesh(geometry, wireframeMaterial);
mesh.add(wireframe);
mesh.scale.set(0.1, 0.1, 0.1);
const redColor = new THREE.Color(1, 0, 0);
console.log(mesh);
// mesh.children[0].material.color = redColor;
const light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 0, 1);
this.scene.add(light);
this.scene.add(mesh);
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
(error) => {
console.error(error);
}
);
},
You are rendering the wireframe version too, which consists of lines in screen-space. As you zoom out, these lines maintain the same width in pixels, thus covering everything else.
Do you wish to render the fireframe too? If not, don't. If you do, then consider hiding it as the user zooms out.
Actually I am using ArcGIS API for JavaScript 4.7 and i have a custom internal layer . I want to get name of place particular area when draw polyline the column name is (PLC_NAME) . How to achieve that ?
Suppose I draw a area through polyline. In this area there are places . Now I need to get name of these places .
you can find the using code in below i am using the TileLayer.
require([
"esri/views/MapView",
"esri/Map",
"esri/Basemap",
"esri/layers/TileLayer",
"esri/layers/MapImageLayer",
"esri/widgets/Sketch/SketchViewModel",
"esri/geometry/geometryEngine",
"esri/widgets/CoordinateConversion",
"esri/geometry/support/webMercatorUtils",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/config",
"esri/core/urlUtils",
"esri/widgets/Search",
"esri/tasks/Locator",
"esri/layers/FeatureLayer",
"esri/widgets/Expand",
"dojo/domReady!"
], function (
MapView, Map, Basemap, TileLayer, MapImageLayer,
SketchViewModel,
geometryEngine,
CoordinateConversion,
webMercatorUtils,
Graphic, GraphicsLayer, esriConfig, urlUtils,Search,Locator,FeatureLayer,Expand
) {
esriConfig.request.proxyUrl = "xxxxxxxxxxxxxxx";
urlUtils.addProxyRule({
urlPrefix: "xxxxxxxxxxxxxxxxxxx",
proxyUrl: "xxxxxxxxxxxxxxxxxx"
});
var tempGraphicsLayer = new GraphicsLayer();
var saveGraphicsLayer = new GraphicsLayer();
var updateGraphic;
let highlight = null;
'xxxxxxxxxxxxxxxxxxxxxxxxx';
var myMap;
var layer = new TileLayer({
url: mapUrl
});
var towerLayer = new MapImageLayer({
url: 'xxxxxxxxxxxxxxxxxxxxxxx'
});
myMap = new Map({
layers: [layer, tempGraphicsLayer, saveGraphicsLayer]
});
myMap.add(towerLayer);
view = new MapView({
center: [-55.1683665, 39.951817],
container: "viewDiv",
map: myMap,
zoom: 14
});
var ccWidget = new CoordinateConversion({
view: view
});
// Adds the search widget below other elements in
// the top left corner of the view
view.ui.add(searchWidget, {
position: "top-right",
index: 1
});
view.ui.add(ccWidget, "bottom-left");
view.ui.add("topbar", "top-right");
var pointSymbol = { // symbol used for points
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
style: "square",
color: "#8A2BE2",
size: "16px",
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 3 // points
}
}
var polylineSymbol = { // symbol used for polylines
type: "simple-line", // autocasts as new SimpleLineSymbol()
color: "#8A2BE2",
width: "4",
style: "dash"
}
var polygonSymbol = { // symbol used for polygons
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: "rgba(138,43,226, 0.8)",
style: "solid",
outline: {
color: "white",
width: 1
}
}
var polygonBoundrySymbol = { // symbol used for polygons
type: "simple-line", // autocasts as new SimpleFillSymbol()
color: "red"
}
// ################## U R HERE ################## ################## U R HERE ##################
################## U R HERE ##################
let drawBoundry = function(){
//let boundryJson = '&G_GEO_LIMITS.';
let boundryJson = $v('P0_USER_LIMITS');
if(boundryJson){
// let boundry = Graphic.fromJSON(JSON.parse('&G_GEO_LIMITS.'));
let boundry = Graphic.fromJSON(JSON.parse(boundryJson));
boundry.symbol = polygonBoundrySymbol;
tempGraphicsLayer.add(boundry);
return boundry;
}
}
/*
let boundry = drawBoundry();
*/
view.when(function () {
$('.esri-view-root').on('click', '.esri-print__export-button', function(e){
//console.log('event bubbling', e);
//console.log('event bubbling this', this);
e.preventDefault();
saveExportedImg();
});
// create a new sketch view model
var sketchViewModel = new SketchViewModel({
view: view,
layer: tempGraphicsLayer,
pointSymbol: pointSymbol,
polylineSymbol: polylineSymbol,
polygonSymbol: polygonSymbol
});
//setUpClickHandler();
// ************************************************************
// Get the completed graphic from the event and add it to view.
// This event fires when user presses
// * "C" key to finish sketching point, polygon or polyline.
// * Double-clicks to finish sketching polyline or polygon.
// * Clicks to finish sketching a point geometry.
// ***********************************************************
sketchViewModel.on("draw-complete", addGraphic);
sketchViewModel.on("update-complete", addGraphic);
sketchViewModel.on("update-cancel", addGraphic);
sketchViewModel.on("vertex-add", addGraphic);
function addGraphic(evt) {
// console.log ('graphic.geometry',evt.geometry)
//let currentGraphic = popActiveGraphic(tempGraphicsLayer);
let currentGraphic = saveGraphicsLayer.graphics.items.pop();
var geometry = evt.geometry;
var vertices = evt.vertices;
var symbol;
var attr = {
Name: "Selected Area",
X: $v('P24_X'),
Y: $v('P24_Y')
};
// Choose a valid symbol based on return geometry
switch (geometry.type) {
case "point":
symbol = pointSymbol;
break;
case "polyline":
symbol = polylineSymbol;
break;
default:
symbol = polygonSymbol;
break;
}
// Create a new graphic; add it to the GraphicsLayer
// console.log("b4 graphic");
geometry = webMercatorUtils.webMercatorToGeographic(geometry)
/*if(boundry){
var contains = geometryEngine.contains(boundry.geometry, geometry);
var within = geometryEngine.within(geometry, boundry.geometry);
} else {*/
var within = true;
//}
if(within){
let graphic = new Graphic({
geometry: geometry,
symbol: symbol,
//attributes: attr,
popupTemplate: {
title: "{Name}",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "X"
}, {
fieldName: "Y"
}]
}]
}
});
tempGraphicsLayer.add(graphic);
if(currentGraphic){
//currentGraphic.geometry.rings.push(geometry.rings[0]);
geometry.rings.forEach( ring => currentGraphic.geometry.addRing(ring));
//currentGraphic.geometry.addRing(geometry.rings);
//console.log('current active', geometry);
// console.log('current graphic', currentGraphic.geometry);
graphic = currentGraphic;
}
var saveObj = graphic.toJSON();
// console.log('saveObj', saveObj);
$x('P24_JSON').value = JSON.stringify(saveObj);
} else {
apex.message.alert('&G_MAP_BOUNDRY_MSG.');
}
updateGraphic = null;
}
function addMultiGraph(evt1) {
//let currentGraphic = popActiveGraphic(tempGraphicsLayer);
let currentGraphic = saveGraphicsLayer.graphics.items.pop();
var geometry = evt1.geometry;
var vertices = evt1.vertices;
var symbol;
// Choose a valid symbol based on return geometry
switch (geometry.type) {
case "point":
symbol = pointSymbol;
break;
case "polyline":
symbol = polylineSymbol;
break;
default:
symbol = polygonSymbol;
break;
}
//console.log("ring",geometry.rings )
let graphic = new Graphic({
geometry: geometry,
symbol: symbol,
//attributes: attr,
popupTemplate: {
title: "{Name}",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "X"
}, {
fieldName: "Y"
}]
}]
}
});
tempGraphicsLayer.add(graphic);
if(currentGraphic){
geometry.rings.forEach( ring => currentGraphic.geometry.addRing(ring));
}
var saveObj1 = graphic.toJSON();
//console.log('saveObj', graphic);
$x('P24_JSON').value = JSON.stringify(saveObj1);
updateGraphic = null;
}
window.loadGraphic = function(polygon){
if(polygon===undefined || polygon === ''){
console.error('no polygon');
} else {
var graphic = Graphic.fromJSON(JSON.parse(polygon));
if (graphic.geometry){
addMultiGraph(graphic);
//*********************************************************************
view.center.longitude = graphic.geometry.centroid.longitude;
view.center.latitude = graphic.geometry.centroid.latitude;
view.center = [graphic.geometry.centroid.longitude,
graphic.geometry.centroid.latitude];
view.zoom = 12;
}
}
}
// *************************************
// activate the sketch to create a point
// *************************************
var drawPointButton = document.getElementById("pointButton");
drawPointButton.onclick = function () {
// set the sketch to create a point geometry
sketchViewModel.create("point");
setActiveButton(this);
};
// ****************************************
// activate the sketch to create a polyline
// ****************************************
var drawLineButton = document.getElementById("polylineButton");
drawLineButton.onclick = function () {
// set the sketch to create a polyline geometry
sketchViewModel.create("polyline");
setActiveButton(this);
};
var drawPolygonButton = document.getElementById("polygonButton");
drawPolygonButton.onclick = function () {
// set the sketch to create a polygon geometry
sketchViewModel.create("polygon");
setActiveButton(this);
};
// ***************************************
// activate the sketch to create a rectangle
// ***************************************
var drawRectangleButton = document.getElementById(
"rectangleButton");
drawRectangleButton.onclick = function () {
// set the sketch to create a polygon geometry
sketchViewModel.create("rectangle");
setActiveButton(this);
};
document.getElementById("resetBtn").onclick = function () {
sketchViewModel.reset();
tempGraphicsLayer.removeAll();
saveGraphicsLayer.removeAll();
setActiveButton();
drawBoundry();
};
function setActiveButton(selectedButton) {
// focus the view to activate keyboard shortcuts for sketching
view.focus();
var elements = document.getElementsByClassName("active");
for (var i = 0; i < elements.length; i++) {
elements[i].classList.remove("active");
}
if (selectedButton) {
selectedButton.classList.add("active");
}
}
// ************************************************************************************
// set up logic to handle geometry update and reflect the update on "tempGraphicsLayer"
// ************************************************************************************
function setUpClickHandler() {
view.on("click", function (evt) {
view.hitTest(evt).then(function (response) {
var results = response.results;
// Found a valid graphic
if (results.length && results[results.length - 1]
.graphic) {
// Check if we're already editing a graphic
if (!updateGraphic) {
// Save a reference to the graphic we intend to update
updateGraphic = results[results.length - 1].graphic;
// Remove the graphic from the GraphicsLayer
// Sketch will handle displaying the graphic while being updated
tempGraphicsLayer.remove(updateGraphic);
sketchViewModel.update(updateGraphic.geometry);
}
}
});
});
}
function errorCallback(error) {
console.log('error:', error);
}
// ************************************************************************************
// returns graphic object if drawn on the map to contcat new graphics to it
// ************************************************************************************
function popActiveGraphic(graphicsLayer){
let length = graphicsLayer.graphics.length;
let count = 0;
if($v('P0_USER_LIMITS').length > 0){
count++;
}
if(length > count){ //active drawing detected
let result = graphicsLayer.graphics.items[length-1];
graphicsLayer.remove(result);
return result;
}
}
});
});
OK, you can resolve the queries on the client or on the server. Depends on your task what options you can pick on.
If you are going to use a spatial query, like the one you mention, and you will apply it on a FeatureLayer, you could solve it on the client. This is a good solution because you already have the features, you are seeing them. Here you have a question whis this situation, how-to-get-get-name-of-hospital-or-street-in-particular-area-when-draw-polyline.
Now, If you need to query something that might not be in your extent (you don't have the features) or you are not using a FeatureLayer, you probably will need to command the server to do this. But don't worry the library has several tools to work with, like QueryTask.
Here you have the same example of the answer link before but using QueryTask.
<html>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='initial-scale=1, maximum-scale=1, user-scalable=no'>
<title>Select Feature With Polygon</title>
<style>
html,
body {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#viewDiv {
padding: 0;
margin: 0;
height: 400px;
width: 100%;
}
#namesDiv {
margin: 10px;
height: 200px;
width: 100%;
font-style: italic;
font-weight: bold;
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
color: green;
overflow: auto;
}
</style>
<link rel='stylesheet' href='https://js.arcgis.com/4.15/esri/css/main.css'>
<script src='https://js.arcgis.com/4.15/'></script>
<script>
require([
'esri/Map',
'esri/views/MapView',
'esri/layers/MapImageLayer',
'esri/layers/GraphicsLayer',
'esri/widgets/Sketch/SketchViewModel',
'esri/Graphic',
'esri/widgets/Expand',
'esri/tasks/QueryTask',
'esri/tasks/support/Query'
], function (
Map,
MapView,
MapImageLayer,
GraphicsLayer,
SketchViewModel,
Graphic,
Expand,
QueryTask,
Query
) {
let highlight = null;
const states = new MapImageLayer({
url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer'
});
const queryTask = new QueryTask({
url: 'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/2'
});
const polygonGraphicsLayer = new GraphicsLayer();
const selected = new GraphicsLayer();
const map = new Map({
basemap: 'streets',
layers: [states, polygonGraphicsLayer, selected]
});
const view = new MapView({
container: 'viewDiv',
map: map,
center: [-75.1683665, 39.951817],
zoom: 8
});
const sketchViewModel = new SketchViewModel({
view: view,
layer: polygonGraphicsLayer,
pointSymbol: {
type: 'simple-marker',
color: [255, 255, 255, 0],
size: '1px',
outline: {
color: 'gray',
width: 0
}
}
});
sketchViewModel.on('create', function (event) {
if (event.state === 'complete') {
polygonGraphicsLayer.remove(event.graphic);
selectFeatures(event.graphic.geometry);
}
});
const namesDiv = document.getElementById('namesDiv');
view.ui.add('select-by-polygon', 'top-left');
const selectButton = document.getElementById('select-by-polygon');
selectButton.addEventListener('click', function () {
clearUpSelection();
sketchViewModel.create('polygon');
});
function selectFeatures(geometry) {
selected.removeAll();
const query = new Query();
query.returnGeometry = true;
query.outFields = ['*'];
query.geometry = geometry;
queryTask
.execute(query)
.then(function (results) {
const graphics = results.features.map(r => {
r.symbol = {
type: 'simple-fill',
fill: 'none',
outline: {
color: 'cyan',
width: 2
}
};
return r;
});
selected.addMany(graphics);
namesDiv.innerHTML = graphics.map(g => g.attributes.NAME).join(',');
})
.catch(errorCallback);
}
function clearUpSelection() {
selected.removeAll();
namesDiv.innerHTML = null;
}
function errorCallback(error) {
console.log('error:', error);
}
});
</script>
</head>
<body>
<div id='viewDiv'>
<div
id="select-by-polygon"
class="esri-widget esri-widget--button esri-widget esri-interactive"
title="Select counties by polygon"
>
<span class="esri-icon-checkbox-unchecked"></span>
</div>
</div>
<div id="namesDiv"></div>
</body>
</html>
To close I leave you this link to the documentation that explains very well all the possibilities, pros and cons.
I am trying to implement orbitControls in my react application. I have loaded 3d model GraphicsView
of expo-graphics. Model loaded perfectly, now i need to rotate the 3D model with screen drag. For
this i have added orbitControls, which is not working properly. Model did'nt rotate with screen
drag.Please help what i need to do to do to rotate 3D model in my react app.
Here is my model class.
```
import React from 'react';
import ExpoTHREE, { THREE } from 'expo-three';
import { GraphicsView } from 'expo-graphics';
import OrbitControls from 'three-orbitcontrols';
class Model extends React.Component {
componentDidMount() {
THREE.suppressExpoWarnings();
}
// When our context is built we can start coding 3D things.
onContextCreate = async ({ gl, pixelRatio, width, height }) => {
// Create a 3D renderer
this.renderer = new ExpoTHREE.Renderer({
gl,
pixelRatio,
width,
height,
});
// We will add all of our meshes to this scene.
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0x3d392f);
//this.scene.fog = new THREE.Fog( 0xa0a0a0, 10, 50 );
this.camera = new THREE.PerspectiveCamera(12, width/height, 1, 1000);
this.camera.position.set(3, 3, 3);
this.camera.lookAt(0, 0, 0);
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.rotateSpeed = 2.0;
this.controls.zoomSpeed = 1.2;
this.controls.panSpeed = 0.8;
this.controls.noPan = false;
this.controls.staticMoving = false;
this.controls.dynamicDampingFactor = 0.3;
this.controls.keys = [ 65, 83, 68 ];
this.controls.addEventListener( 'change', this.onRender );
//clock = new THREE.Clock();
//this.scene.add(new THREE.AmbientLight(0xffffff));
var hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
hemiLight.position.set( 0, 20, 0 );
this.scene.add( hemiLight );
var dirLight = new THREE.DirectionalLight( 0xffffff );
dirLight.position.set( - 3, 10, - 10 );
dirLight.castShadow = true;
dirLight.shadow.camera.top = 2;
dirLight.shadow.camera.bottom = - 2;
dirLight.shadow.camera.left = - 2;
dirLight.shadow.camera.right = 2;
dirLight.shadow.camera.near = 0.1;
dirLight.shadow.camera.far = 40;
this.scene.add( dirLight );
await this.loadModel();
};
loadModel = async () => {
const obj = {
"f.obj": require('../assets/models/f.obj')
}
const model = await ExpoTHREE.loadAsync(
obj['f.obj'],
null,
obj
);
// this ensures the model will be small enough to be viewed properly
ExpoTHREE.utils.scaleLongestSideToSize(model, 1);
this.scene.add(model)
};
// When the phone rotates, or the view changes size, this method will be called.
onResize = ({ x, y, scale, width, height }) => {
// Let's stop the function if we haven't setup our scene yet
if (!this.renderer) {
return;
}
this.camera.aspect = width / height;
this.camera.updateProjectionMatrix();
this.renderer.setPixelRatio(scale);
this.renderer.setSize(width, height);
};
// Called every frame.
onRender = delta => {
// Finally render the scene with the Camera
this.renderer.render(this.scene, this.camera);
};
render() {
return (
<GraphicsView
onContextCreate={this.onContextCreate}
onRender={this.onRender}
onResize={this.onResize}
/>
);
}
}
export default Model;
```
Im trying to resize everything on window resize.
I have this function but only seems to resize one layer ( graphLayer.add(drawGraph);)
I thought the code below should resize everything??
function onResize(){
var widowWidth = (window.innerWidth) -yPadding; // width - the padding
var widowHeight = (window.innerHeight) -xPadding; // Height - the padding
stage.setWidth((window.innerWidth) -yPadding);
stage.setHeight((window.innerHeight) -xPadding);
stage.draw();
}
here is a the basics of my code
$(window).resize(onResize);
var graph;
var graphLayer = new Kinetic.Layer();
var BubbleLayer = new Kinetic.Layer();
var tooltipLayer = new Kinetic.Layer();
var widowWidth = (window.innerWidth) -yPadding; // width - the padding
var widowHeight = (window.innerHeight) -xPadding; // Height - the padding
var stage = new Kinetic.Stage({
container: 'graph',
width: widowWidth, // width - the padding
height: widowHeight, // Height - the padding
});
var tooltip = new Kinetic.Label({
opacity: 0.75,
visible: false,
listening: false
});
tooltip.add(new Kinetic.Tag({
.........
}));
tooltip.add(new Kinetic.Text({
.........
}));
var drawGraph = new Kinetic.Shape ({
sceneFunc: function(ctx){
.........
}
ctx.fillStrokeShape(this);
},
stroke: 'black',
strokeWidth: 1
});
var drawGraphquarter = new Kinetic.Shape ({
sceneFunc: function(ctx){
.........
}
},
stroke: 'red',
strokeWidth: 3
});
// build data
$.getJSON( "bubble_data.json", function( data ) {
$.each( data.projects, function(i) {
var bubbleData = [];
.........
bubbleData.push({
.........
});
.........
for(var n = 0; n < bubbleData.length; n++) {
addBubble(bubbleData[n], BubbleLayer);
stage.add(BubbleLayer);
}
});
graphLayer.add(drawGraph);
graphLayer.add(drawGraphquarter);
stage.add(BubbleLayer);
stage.add(graphLayer);
graphLayer.moveToBottom();
tooltipLayer.add(tooltip);
stage.add(tooltipLayer);
});
});
// add bubles to layer
function addBubble(obj, BubbleLayer) {
var bubble = new Kinetic.Shape({
sceneFunc: function(ctx) {
.........
});
BubbleLayer.add(bubble);
}
// calendar quarter
function getQuarter(d) {
.........
}
function onResize(){
var widowWidth = (window.innerWidth) -yPadding; // width - the padding
var widowHeight = (window.innerHeight) -xPadding; // Height - the padding
stage.setWidth((window.innerWidth) -yPadding);
stage.setHeight((window.innerHeight) -xPadding);
stage.draw();
}
Updated my code to this.
var graph;
var xPadding = 10;
var yPadding = 10;
var graphLayer = new Kinetic.Layer();
var graphLayerQuater = new Kinetic.Layer();
var BubbleLayer = new Kinetic.Layer();
var tooltipLayer = new Kinetic.Layer();
var widowWidth = (window.innerWidth) -yPadding; // width - the padding
var widowHeight = (window.innerHeight) -xPadding; // Height - the padding
var stage = new Kinetic.Stage({
container: 'graph',
width: widowWidth,
height: widowHeight,
});
var initialScale = stage.scale(); //returns {x: 1, y: 1}
var initialWidth = (window.innerWidth) -yPadding; // width - the padding
var initialHeight = (window.innerHeight) -xPadding; // Height - the padding
onresize function
window.onresize = function(event) {
var width = (window.innerWidth) -yPadding;
var height =(window.innerHeight) -xPadding;
var xScale = (width / initialWidth) * initialScale.x;
var yScale = (height / initialHeight) * initialScale.y;
var newScale = {x: xScale, y: yScale};
stage.setAttr('width', width);
stage.setAttr('height', height);
stage.setAttr('scale', newScale );
stage.draw();
}