I am trying to resize a canvas element to the width of the window using VueJS. I've seen many examples of this working with vanilla JS, but for whatever reason, with VueJS I can't get the canvas content to re-render.
An example is attached. The example is modified from the vanilla JS version from here: http://ameijer.nl/2011/08/resizable-html5-canvas/
https://codepen.io/bastula/pen/yZXowo
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Canvas Test</title>
</head>
<body>
<div id="app">
<canvas id="image-canvas" ref="imagecanvas" v-bind:width="width" v-bind:height="height" style="
background-color: #000;">
</canvas>
</div>
</body>
</html>
<script type="text/javascript" src="https://unpkg.com/vue"></script>
<script>
const app = new Vue({
el: '#app',
data: function () {
return {
height: 512,
width: 512,
margin: 20,
};
},
mounted() {
window.addEventListener('resize', this.handleResize);
this.handleResize();
},
computed: {
canvas: function () {
return this.$refs.imagecanvas;
},
ctx: function () {
return this.canvas.getContext('2d');
}
},
methods: {
handleResize: function () {
// Calculate new canvas size based on window
this.height = window.innerHeight - this.margin;
this.width = window.innerWidth - this.margin;
this.drawText();
},
drawText: function () {
// Redraw & reposition content
var resizeText = 'Canvas width: ' + this.canvas.width + 'px';
this.ctx.textAlign = 'center';
this.ctx.fillStyle = '#fff';
this.ctx.fillText(resizeText, 200, 200);
}
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize);
}
})
</script>
Solved here: https://forum.vuejs.org/t/resize-canvas-element-based-on-window-change-using-vuejs/55497/2?u=bastula
The solution is to use: nextTick.
So instead of this.drawText() in the handleResize method it should be:
this.$nextTick(() => {
this.drawText();
})
Updated working CodePen can be found here.
Related
I'm trying to use this on my webpage. But when I'm opening the webpage in two different webbrowsers, and when I drag the div, it doesn't update on both, just the one i'm dragging in. Below is the code I'm using. Why is this not working?
Below is index.html in my http://mywebsite.com/myProject/
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script src="http://code.jquery.com/ui/1.10.0/jquery-ui.js"></script>
<script src="socket.io.js"></script>
<script>
$(document).ready(function () {
var socket = io("http://mywebsite.com/myProject/");
socket.on('update_position', function (data) {
var x = data.x;
var y = data.y;
// jquery code to move div here
$("#left").val(x);
$("#top").val(y);
$("#mydiv").css({
left: x + "px",
top: y + "px"
});
});
$("#mydiv").draggable({
drag: function (event, ui) {
var coord = $(this).position();
$("#left").val(coord.left);
$("#top").val(coord.top);
socket.emit('receive_position', {
x: coord.left,
y: coord.top
});
}
});
});
</script>
<style>
.dstyle
{
position: absolute;
width: 50px; height: 50px;
background: #ffb; padding: 5px;
border: 2px solid #999;
}
</style>
</head>
<body>
X: <input type="text" id="left"/>
Y: <input type="text" id="top"/>
<div id="mydiv" class="dstyle">drag me</div>
</body>
And here is the server.js below
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(3000);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
var lastPosition = { x: 0, y: 0 }; // whatever default data
io.sockets.on('connection', function (socket) {
socket.emit('update_position', lastPosition);
socket.on('receive_position', function (data) {
lastPosition = data;
socket.broadcast.emit('update_position', data); // send `data` to all other clients
});
});
Problem solved! The problem was that my webhosting did not support Node JS, so now I am using glitch.com which has free hosting supporting Node JS
When I click and drag my mouse across a scene, it takes two full screen widths to make a 360 degree turn.
Is it possible to adjust the sensitivity of an A-Frame scene?
In case anyone was curious, this is the html I am using:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script src="https://aframe.io/releases/0.5.0/aframe.min.js"></script>
</head>
<body>
<a-scene vr-mode-ui="enabled: false">
<a-assets>
<img id="image" crossorigin="anonymous" src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/sechelt.jpg">
</a-assets>
<a-sky id="image-360" radius="10" src="#image"></a-sky>
</a-scene>
</body>
</html>
<script type="text/javascript">
AFRAME.registerComponent('drag-rotate-component',{
schema : { speed : {default:1}},
init : function(){
this.ifMouseDown = false;
this.x_cord = 0;
this.y_cord = 0;
document.addEventListener('mousedown',this.OnDocumentMouseDown.bind(this));
document.addEventListener('mouseup',this.OnDocumentMouseUp.bind(this));
document.addEventListener('mousemove',this.OnDocumentMouseMove.bind(this));
},
OnDocumentMouseDown : function(event){
this.ifMouseDown = true;
this.x_cord = event.clientX;
this.y_cord = event.clientY;
},
OnDocumentMouseUp : function(){
this.ifMouseDown = false;
},
OnDocumentMouseMove : function(event)
{
if(this.ifMouseDown)
{
var temp_x = event.clientX-this.x_cord;
var temp_y = event.clientY-this.y_cord;
if(Math.abs(temp_y)<Math.abs(temp_x))
{
this.el.object3D.rotateY(temp_x*this.data.speed/100);
}
else
{
this.el.object3D.rotateX(temp_y*this.data.speed/100);
}
this.x_cord = event.clientX;
this.y_cord = event.clientY;
}
}
});
</script>
Source you can adjust the speed, and add the camera component right above the sky
<a-entity camera drag-rotate-component></a-entity>
Demo
You will only need the Y defined
I'm trying to print a specific zone on an Arcgis maps with the JS API (not the extend that is displayed).
I didn't find any method or option to do this so I tried to change the extend and then print the map :
var extent = new esri.geometry.Extent(
-620526.0922336339,
5993991.149960931,
108988.90572005256,
6293624.300838808,
myMap.spatialReference
);
myMap.setExtent(extent, true).then(function() {
console.log('setExtend is finished');
var template = new esri.tasks.PrintTemplate();
template.exportOptions = {
width : 500,
height : 500
};
template.format = 'jpg';
template.layout = 'MAP_ONLY';
var params = new esri.tasks.PrintParameters();
params.map = myMap;
params.template = template;
var printTask = new esri.tasks.PrintTask(urlToThePrintServer);
printTask.execute(params);
});
Since setExtent is asynchonous and return a defered I have to use the 'then' method.
I can see the map moving but the defered doesn't seem to works ... (I don't see the console.log()).
is there another way to print a specific extend of a map ?
if not why is the 'then' method never called ?
(I'm using the 3.12 JS API)
Your code looks good to me, though obviously you didn't post all your JavaScript or any of your HTML. Maybe you're not requiring the modules you need. Or maybe your code is trying to run before the map is loaded, though that's unlikely because as you say, the map does move. Or maybe something else is wrong.
I put a full working example at http://jsfiddle.net/06jtccx0/ . Hopefully you can compare that to what you're doing and figure out what is wrong with your code. Here's the same code for your convenience:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
<title>Simple Map</title>
<link rel="stylesheet" href="http://js.arcgis.com/3.13/esri/css/esri.css">
<style>
html, body, #map {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
body {
background-color: #FFF;
overflow: hidden;
font-family: "Trebuchet MS";
}
</style>
<script src="http://js.arcgis.com/3.13/"></script>
<script>
var myMap;
var urlToThePrintServer = "http://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task";
require(["esri/map", "dojo/domReady!"], function(Map) {
myMap = new Map("map", {
basemap: "topo", //For full list of pre-defined basemaps, navigate to http://arcg.is/1JVo6Wd
center: [-122.45, 37.75], // longitude, latitude
zoom: 13
});
myMap.on("load", function(map) {
var extent = new esri.geometry.Extent(
-620526.0922336339,
5993991.149960931,
108988.90572005256,
6293624.300838808,
myMap.spatialReference
);
myMap.setExtent(extent, true).then(function() {
console.log('setExtend is finished');
require([
"esri/tasks/PrintTemplate",
"esri/tasks/PrintParameters",
"esri/tasks/PrintTask"
], function(
PrintTemplate,
PrintParameters,
PrintTask
) {
var template = new PrintTemplate();
template.exportOptions = {
width : 500,
height : 500
};
template.format = 'jpg';
template.layout = 'MAP_ONLY';
var params = new PrintParameters();
params.map = myMap;
params.template = template;
var printTask = new PrintTask(urlToThePrintServer);
printTask.execute(params, function(response) {
console.log("The printed document is at " + response.url);
window.open(response.url);
});
});
});
});
});
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
I want to execute a JavaScript code on load of the Shadow DOM in my custom element.
I tried the following code but it did not work
x-component.html:
<template id="myTemplate">
<div>I am custom element</div>
</template>
<script>
var doc = this.document._currentScript.ownerDocument;
var XComponent = document.registerElement('x-component', {
prototype: Object.create(HTMLElement.prototype, {
createdCallback: {
value: function() {
var root = this.createShadowRoot();
var template = doc.querySelector('#myTemplate');
var clone = document.importNode(template.content, true);
clone.addEventListener('load', function(e) {
alert('Shadow DOM loaded!');
});
root.appendChild(clone);
}
}
})
});
</script>
Then I use it in another html as follows -
index.html:
<!doctype html>
<html >
<head>
<script src="bower_components/webcomponentsjs/webcomponents.min.js"></script>
<link rel="import" href="x-component.html">
</head>
<body>
<x-component></x-component>
</body>
</html>
The doc variable is used as I am using Polymer webcomponents.js polyfill and the polyfill needs it.
What is the right syntax to listen to load event of Shadow DOM?
AFAIK, the only way to achieve this is to use MutationObserver:
attachedCallback: {
value: function() {
var root = this.createShadowRoot();
var template = document.querySelector('#myTemplate');
var clone = document.importNode(template.content, true);
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if(mutation.addedNodes) { // this is definitely a subject to change
alert('Shadow is loaded');
};
});
})
observer.observe(root, { childList: true });
root.appendChild(clone);
}
}
I would be glad to know if there is more elegant way, but for now I use this one.
Live preview: http://plnkr.co/edit/YBh5i2iCOwqpgsUU6En8?p=preview
I am trying to create a popup window in a map. I have tree layers in my program; the first two layers are working; the third layer where I have template is defined doesn't work, though. In the console I get following errors:
Error: Unable to draw graphic (null): Unable to complete operation.
...usePost,v=h.crossOrigin):A=!!h);g=e.mixin({},g);g._ssl&&(g.url=g.url.replace(/^h...
I tried to solve this problem, by adding time between the layers. It didn't work.
Below is my code. Please let me know if I am making any mistake. Thanks!
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--The viewport meta tag is used to improve the presentation and behavior of the samples
on iOS devices-->
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title> Trees Location</title>
<link rel="stylesheet" href="http://js.arcgis.com/3.11/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="http://js.arcgis.com/3.11/esri/css/esri.css">
<script src="http://js.arcgis.com/3.11/"></script>
<script>
var map;
require(["esri/config", "esri/map","esri/dijit/Popup",
"dojo/dom-construct",
"esri/dijit/PopupTemplate",
"esri/layers/FeatureLayer",
"esri/symbols/SimpleMarkerSymbol",
"esri/tasks/GeometryService",
"esri/layers/ArcGISDynamicMapServiceLayer",
"esri/layers/ArcGISTiledMapServiceLayer",
"esri/Color",
"dojo/domReady!"],
function (esriConfig, Map,Popup,domConstruct, PopupTemplate, FeatureLayer,SimpleMarkerSymbol, GeometryService, ArcGISDynamicMapServiceLayer, ArcGISTiledMapServiceLayer, Color ) {
esriConfig.defaults.geometryService = new GeometryService("http://tasks.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");
var popupOptions = {
markerSymbol: new SimpleMarkerSymbol("circle", 32, null,
new Color([0, 0, 0, 0.25])),
marginLeft: "20",
marginTop: "20"
};
var popup = new Popup(popupOptions, domConstruct.create("div"));
map = new Map("map", {
center: [-76.756, 40.241],
zoom: 8,
infoWindow: popup
});
var popupTemplate = new PopupTemplate({
title: "{MEMORIAL}",
fieldInfos: [
{
fieldName: "TREEDONOR",
visible: true,
label: "Type"
},
{
fieldName: "TREESPECIES",
visible: true,
label: "Type"
},
{
fieldName: "TREEVARIETY",
visible: true,
label: "Type"
}
]
});
var customBasemap = new ArcGISTiledMapServiceLayer(
"");
map.addLayer(customBasemap);
/* setTimeout(function(){
console.log("pausing a few seconds");
map.addLayer(customBasemap);
},1000); */
var treeLayer = new ArcGISDynamicMapServiceLayer(
"");
// map.addLayer(treeLayer);
setTimeout(function(){
console.log("pausing a few seconds");
map.addLayer(treeLayer);
},1000);
var featureLayer = new FeatureLayer("",
{
infoTemplate: popupTemplate,
outFields: ["TREEDONOR","TREESPECIES","TREEVARIETY", "MEMORIAL"]
});
featureLayer.setDefinitionExpression("MEMORIAL != ''");
map.addLayer(featureLayer);
});
</script>
</head>
<body class="claro">
<div align="center"><strong> Trees Listing </strong><hr>
<i><a target="_self" href="listingtrees.html">Listing</a> | <a target="_self" href="locationtrees.html">Locations </a></i>
</div>
<br>
<div id="map" >
</div>
</body>
</html>