how to create a barcode scanner with quagga with fixed scanning canvas - vue.js

I'm on Nuxt 2.15.4 and using Quagga2. I want to create a scanner like mobile scanners where the camera is full screen and there is a blue rectangle that the barcode must be placed inside of, and after scanning there will be a red line through the barcode canvas. With Quagga.js I can manipulate the CSS and area property in canvas but it cause 2 problems:
The actual scanning zone will be messed up and I don't know where the scanning exactly happens.
The successful red line-through style will be messed up.
Also, after a successful scan I need the red line-through to remain and not disappear and no scanning happen for a period of time (so I can decide to continue scanning or do something with result).
Here is the code I implemented on in app (also need help on activating torch and zoom):
<template>
<section id="container" class="container">
<div id="interactive" class="viewport"></div>
{{code}}
</section>
</template>
<script>
import Quagga from '#ericblade/quagga2';
export default {
data() {
return {
code:[]
};
},
methods:{
async checkDevice() {
let md = navigator.mediaDevices;
if (!md || !md.enumerateDevices) return false;
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.some((device) => "videoinput" === device.kind);
},
initQuagga(){
Quagga.init({
inputStream : {
name : "Live",
type : "LiveStream",
area: {
top: "0%",
right: "0%",
left: "0%",
bottom: "0%",
},
},
locate: false,
decoder : {
readers : [
"ean_reader",
],
}
},(err)=>{
if(err){
return
}
// this.checkCapabilities();
this.startQuagga()
});
},
// checkCapabilities(){
// var track = Quagga.CameraAccess.getActiveTrack();
// var capabilities = {};
// if (typeof track.getCapabilities === 'function') {
// capabilities = track.getCapabilities();
// }
// this.applySettingsVisibility('zoom', capabilities.zoom);
// this.applySettingsVisibility('torch', capabilities.torch);
// },
// applySetting: function(setting, value) {
// var track = Quagga.CameraAccess.getActiveTrack();
// if (track && typeof track.getCapabilities === 'function') {
// switch (setting) {
// case 'zoom':
// return track.applyConstraints({advanced: [{zoom: parseFloat(value)}]});
// case 'torch':
// return track.applyConstraints({advanced: [{torch: !!value}]});
// }
// }
// },
startQuagga(){
Quagga.start()
Quagga.onProcessed(function (result) {
let drawingCtx = Quagga.canvas.ctx.overlay,
drawingCanvas = Quagga.canvas.dom.overlay;
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
result.boxes.filter(function (box) {
return box !== result.box;
}).forEach(function (box) {
Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "#00F", lineWidth: 2});
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "#008", lineWidth: 2});
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
}
}
})
Quagga.onDetected(this.onDetected);
},
onDetected(data) {
let barCodeData = data.codeResult.code;
console.log(barCodeData);
},
},
async mounted(){
let data = await this.checkDevice();
if (data) {
this.initQuagga();
}
},
beforeDestroy(){
Quagga.stop()
}
}
</script>
<style lang="scss">
#container {
width: 640px;
margin: 20px auto;
padding: 10px;
}
#interactive.viewport {
width: 640px;
height: 480px;
}
#interactive.viewport canvas, video {
float: left;
width: 640px;
height: 480px;
}
#interactive.viewport canvas.drawingBuffer, video.drawingBuffer {
margin-left: -640px;
}
</style>

Related

Convert Pell.js to Vue component for Customizing

I am trying to convert from pell rich text editor to vue component. I have downloaded pell.js and converted it to vue component but I meet some issues now.
I transfer all datas and methods from pell to vue component.
And I called this.init function in created() method. And it shows that this.defaultActions which defined in datas() is not defined in init functions.
Please give me any advice. Thanks..
Here is my vue component
<template>
<div class="content">
<h1>pell</h1>
<div id="editor" class="pell"></div>
<div style="margin-top:20px;">
<h3>Text output:</h3>
<div id="text-output"></div>
</div>
<div style="margin-top:20px;">
<h3>HTML output:</h3>
<pre id="html-output"></pre>
</div>
</div>
</template>
<script>
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
export default {
data: ()=> ({
defaultParagraphSeparatorString : 'defaultParagraphSeparator',
formatBlock : 'formatBlock',
defaultActions: {
bold: {
icon: '<b>B</b>',
title: 'Bold',
state: function state() {
return this.queryCommandState('bold');
},
result: function result() {
return this.exec('bold');
}
},
italic: {
icon: '<i>I</i>',
title: 'Italic',
state: function state() {
return this.queryCommandState('italic');
},
result: function result() {
return this.exec('italic');
}
},
underline: {
icon: '<u>U</u>',
title: 'Underline',
state: function state() {
return this.queryCommandState('underline');
},
result: function result() {
return this.exec('underline');
}
},
strikethrough: {
icon: '<strike>S</strike>',
title: 'Strike-through',
state: function state() {
return this.queryCommandState('strikeThrough');
},
result: function result() {
return this.exec('strikeThrough');
}
},
heading1: {
icon: '<b>H<sub>1</sub></b>',
title: 'Heading 1',
result: function result() {
return this.exec('formatBlock', '<h1>');
}
},
heading2: {
icon: '<b>H<sub>2</sub></b>',
title: 'Heading 2',
result: function result() {
return this.exec('formatBlock', '<h2>');
}
},
paragraph: {
icon: '¶',
title: 'Paragraph',
result: function result() {
return this.exec('formatBlock', '<p>');
}
},
quote: {
icon: '“ ”',
title: 'Quote',
result: function result() {
return this.exec('formatBlock', '<blockquote>');
}
},
olist: {
icon: '#',
title: 'Ordered List',
result: function result() {
return this.exec('insertOrderedList');
}
},
ulist: {
icon: '•',
title: 'Unordered List',
result: function result() {
return this.exec('insertUnorderedList');
}
},
code: {
icon: '</>',
title: 'Code',
result: function result() {
return this.exec('formatBlock', '<pre>');
}
},
line: {
icon: '―',
title: 'Horizontal Line',
result: function result() {
return this.exec('insertHorizontalRule');
}
},
link: {
icon: '🔗',
title: 'Link',
result: function result() {
var url = window.prompt('Enter the link URL');
if (url) this.exec('createLink', url);
}
},
image: {
icon: '📷',
title: 'Image',
result: function result() {
var url = window.prompt('Enter the image URL');
if (url) this.exec('insertImage', url);
}
}
},
defaultClasses: {
actionbar: 'pell-actionbar',
button: 'pell-button',
content: 'pell-content',
selected: 'pell-button-selected'
},
}),
created(){
console.log("this.defaultActions", this.defaultActions);
this.init(
{
element: document.getElementById('editor'),
defaultParagraphSeparator: 'p',
// actions: [
// 'bold',
// 'italic',
// 'underline',
// 'strikethrough'
// ],
onChange: function (html) {
document.getElementById('text-output').innerHTML = html
document.getElementById('html-output').textContent = html
}
}
);
},
methods:{
addEventListener(parent, type, listener) {
return parent.addEventListener(type, listener);
},
appendChild(parent, child) {
return parent.appendChild(child);
},
createElement(tag) {
return document.createElement(tag);
},
queryCommandState(command) {
return document.queryCommandState(command);
},
queryCommandValue(command) {
return document.queryCommandValue(command);
},
exec(command) {
var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
return document.execCommand(command, false, value);
},
init(settings){
Object.keys(this.defaultActions).map(function (action) {
console.log("action", action)
});
var actions = settings.actions ? settings.actions.map(function (action) {
if (typeof action === 'string') return this.defaultActions[action];
else if (this.defaultActions[action.name]) return _extends({}, this.defaultActions[action.name], action);
return action;
}) : Object.keys(this.defaultActions).map(function (action) {
console.log("action", action)
console.log("sss", this.defaultActions)
// return this.defaultActions[action];
});
var classes = _extends({}, this.defaultClasses, settings.classes);
var defaultParagraphSeparator = settings[this.defaultParagraphSeparatorString] || 'div';
var actionbar = this.createElement('div');
actionbar.className = classes.actionbar;
this.appendChild(settings.element, actionbar);
var content = settings.element.content = this.createElement('div');
content.contentEditable = true;
content.className = classes.content;
content.oninput = function (_ref) {
var firstChild = _ref.target.firstChild;
if (firstChild && firstChild.nodeType === 3) this.exec(this.formatBlock, '<' + defaultParagraphSeparator + '>');else if (content.innerHTML === '<br>') content.innerHTML = '';
settings.onChange(content.innerHTML);
};
content.onkeydown = function (event) {
if (event.key === 'Enter' && this.queryCommandValue(this.formatBlock) === 'blockquote') {
setTimeout(function () {
return this.exec(this.formatBlock, '<' + defaultParagraphSeparator + '>');
}, 0);
}
};
this.appendChild(settings.element, content);
actions.forEach(function (action) {
var button = this.createElement('button');
button.className = classes.button;
button.innerHTML = action.icon;
button.title = action.title;
button.setAttribute('type', 'button');
button.onclick = function () {
return action.result() && content.focus();
};
if (action.state) {
var handler = function handler() {
return button.classList[action.state() ? 'add' : 'remove'](classes.selected);
};
this.addEventListener(content, 'keyup', handler);
this.addEventListener(content, 'mouseup', handler);
this.addEventListener(button, 'click', handler);
}
this.appendChild(actionbar, button);
});
if (settings.styleWithCSS) this.exec('styleWithCSS');
this.exec(this.defaultParagraphSeparatorString, defaultParagraphSeparator);
return settings.element;
}
}
}
</script>
<style>
.content {
box-sizing: border-box;
margin: 0 auto;
max-width: 600px;
padding: 20px;
}
#html-output {
white-space: pre-wrap;
}
.pell {
border: 1px solid rgba(10, 10, 10, 0.1);
box-sizing: border-box; }
.pell-content {
box-sizing: border-box;
height: 300px;
outline: 0;
overflow-y: auto;
padding: 10px; }
.pell-actionbar {
background-color: #FFF;
border-bottom: 1px solid rgba(10, 10, 10, 0.1); }
.pell-button {
background-color: transparent;
border: none;
cursor: pointer;
height: 30px;
outline: 0;
width: 30px;
vertical-align: bottom; }
.pell-button-selected {
background-color: #F0F0F0; }
</style>
You should use arrow functions in the block mapping actions, preserves this from the surrounding scope
var actions = settings.actions
? settings.actions.map(action => { // arrow function here
if (typeof action === "string") return this.defaultActions[action];
else if (this.defaultActions[action.name])
return _extends({}, this.defaultActions[action.name], action);
return action
})
: Object.keys(this.defaultActions).map(action => { // arrow function here
console.log("action", action)
console.log("sss", this.defaultActions);
// return this.defaultActions[action];
});
Just for reference, you can also use the sample Vue code given in the pell repository
(or parts thereof, e.g styles)
<template>
<div>
<h6>Editor:</h6>
<div id="pell" class="pell" />
<h6>HTML Output:</h6>
<pre id="pell-html-output"></pre>
</div>
</template>
<script>
import pell from 'pell'
export default {
methods: {
ensureHTTP: str => /^https?:\/\//.test(str) && str || `http://${str}`
},
mounted () {
pell.init({
element: document.getElementById('pell'),
onChange: html => {
window.document.getElementById('pell-html-output').textContent = html
},
actions: [
'bold', 'italic', 'underline', 'strikethrough', 'heading1', 'heading2',
'paragraph', 'quote', 'olist', 'ulist', 'code', 'line',
{
name: 'image',
result: () => {
const url = window.prompt('Enter the image URL')
if (url) pell.exec('insertImage', this.ensureHTTP(url))
}
},
{
name: 'link',
result: () => {
const url = window.prompt('Enter the link URL')
if (url) pell.exec('createLink', this.ensureHTTP(url))
}
}
]
})
}
}
</script>
<style>
.pell {
border: 2px solid #000;
border-radius: 0;
box-shadow: none;
}
#pell-html-output {
margin: 0;
white-space: pre-wrap;
}
</style>

Loading Vue component based on (changeable) variable

total newbie with Vue.js here, so sorry if I'm missing something obvious.
I want to load components based on the content of a variable - so if the content of my variable changes, I want the component to change accordingly. I have all components imported (e.g. import Project1 from "#/components/Project1";), which again is saved in components: {'p1': Project1}
I use <component :is="this.goTo.page"/>
with goTo.page being defined in data as data() {return {goTo: {page: "p1"}}}.
The problem seems to be the reactivness of goTo.page. I update it via this.$set(this.goTo, "page", "p2");. When running, i get the error Uncaught TypeError: Cannot read property 'page' of undefined, which I honestly don't understand, since its initialized with "p1".
import * as Matter from "matter-js";
import Project1 from "#/components/Project1";
import Project2 from "#/components/Project2";
import Project3 from "#/components/Project3";
export default {
name: "Work",
components: {
'p1': Project1,
'p2': Project2,
'p3': Project3
},
data() {
return {
goTo: {
page: "p1"
}
}
},
methods: {
startMatter: function () {
let harrie = require('#/assets/img/harrie.png');
let kub = require('#/assets/img/kub.png');
let jacs = require('#/assets/img/jacs.png');
let container = document.getElementById('threecontainerWork');
let nameTag = document.getElementById("title");
let width = container.offsetWidth;
let height = container.offsetHeight;
let engine = Matter.Engine.create({});
let renderer = Matter.Render.create({
element: document.getElementById('matterContainer'),
canvas: container,
engine: engine,
options: {
width: width,
height: height,
wireframes: false
}
})
let borderLeft = Matter.Bodies.rectangle(0, 0, 1, height * 2, {isStatic: true});
let borderRight = Matter.Bodies.rectangle(width, 0, 1, height * 2, {isStatic: true});
let roof = Matter.Bodies.rectangle(container.getBoundingClientRect().left, 0, width * 2, 1, {isStatic: true});
let ground = Matter.Bodies.rectangle(container.getBoundingClientRect().left, height, width * 2, 1, {isStatic: true});
let collider = Matter.Bodies.rectangle(container.offsetWidth / 2, container.offsetHeight, nameTag.offsetWidth, 1, {
isStatic: true,
isSensor: true,
render: {
fillStyle: 'red'
}
});
let nameTagBox = Matter.Bodies.rectangle(container.offsetWidth / 2, container.offsetHeight / 2, nameTag.offsetWidth, nameTag.offsetHeight, {isStatic: true});
let project1 = Matter.Bodies.rectangle(container.offsetWidth / 2, 100, 200, 200, {
render: {
sprite: {
texture: harrie
}
}
});
let project2 = Matter.Bodies.rectangle(201, 0, 200, 200, {
render: {
sprite: {
texture: kub
}
}
});
let project3 = Matter.Bodies.rectangle(1400, 0, 200, 200, {
render: {
sprite: {
texture: jacs
}
}
});
let polyStack = Matter.Composites.stack(container.offsetWidth / 2, 50, 2, 10, 0, 0, function (x, y) {
let sides = Math.round(Matter.Common.random(2, 8));
return Matter.Bodies.polygon(x, y, sides, Matter.Common.random(100, 100));
})
let mouse = Matter.Mouse.create(renderer.canvas);
let mouseConstraint = Matter.MouseConstraint.create(engine, {
mouse: mouse
})
let colStart = Matter.Events.on(engine, 'collisionStart', function (event) {
var pairs = event.pairs;
for (var i = 0, j = pairs.length; i != j; ++i) {
var pair = pairs[i];
if (pair.bodyA === collider) {
switch (pair.bodyB.id) {
case project1.id:
this.$set(this.goTo, 'page', "p1");
break;
case project2.id:
this.$set(this.goTo, 'page', "p2");
break;
case project3.id:
this.$set(this.goTo, 'page', "p3");
break;
}
} else if (pair.bodyB === collider) {
switch (pair.bodyA.id) {
case project1.id:
this.$set(this.goTo, 'page', "p1");
break;
case project2.id:
this.$set(this.goTo, 'page', "p2");
break;
case project3.id:
this.$set(this.goTo, 'page', "p3");
break;
}
}
}
});
let colEnd = Matter.Events.on(engine, 'collisionEnd', function (event) {
var pairs = event.pairs;
for (var i = 0, j = pairs.length; i != j; ++i) {
var pair = pairs[i];
if (pair.bodyA === collider) {
switch (pair.bodyB.id) {
case project1.id:
this.$set(this.goTo, 'page', "noview");
break;
case project2.id:
this.$set(this.goTo, 'page', "noview");
break;
case project3.id:
this.$set(this.goTo, 'page', "noview");
break;
}
} else if (pair.bodyB === collider) {
switch (pair.bodyA.id) {
case project1.id:
this.$set(this.goTo, 'page', "noview");
break;
case project2.id:
this.$set(this.goTo, 'page', "noview");
break;
case project3.id:
this.$set(this.goTo, 'page', "noview");
break;
}
}
}
});
// TODO implement Vue.set(this.goTo, 'page', "p2"); correctly -> Matter Hell
Matter.World.add(engine.world, [ground, borderLeft, borderRight, roof, collider, project1, project2, project3, nameTagBox, polyStack, mouseConstraint, colStart, colEnd]);
Matter.Engine.run(engine);
Matter.Render.run(renderer);
}
},
},
mounted() {
this.$nextTick(function () {
this.startMatter();
})
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
#upperDiv {
position: relative;
width: 98vw;
height: 81vh;
margin: auto auto 1vh auto;
display: flex;
justify-content: center;
align-items: center;
top: 9vh /*Für alle anderen auch*/
}
#title {
position: absolute;
font-family: 'Playfair Display', serif;
font-weight: 600;
font-size: 5rem;
color: #f0f0f0;
padding: 2vh 3vw;
border: 1px solid #f0f0f0;
background-color: #1d1c1c;
z-index: 2;
text-align: center;
}
.threeContainer {
width: 96vw;
height: 70vh;
z-index: 1;
margin-bottom: 0;
}
<template>
<div>
<div id="upperDiv">
<div class="threeContainer" id="matterContainer">
<canvas id="threecontainerWork" class="threeContainer"></canvas>
</div>
<p id="title">My work</p>
</div>
<component :is="goTo.page"/>
</div>
</template>
<component :is="goTo.page"/>
this is not available in <template>. Everything "inside" this, is available.
In addition to the above and per your update,
methods: {
startMatter: function () {
//some matter.js
//if body collision detected:
this.$set(this.goTo, 'page', "p2");
},
},
The second argument of this.$set should be a string with the key name you wish to update.
If that doesn't work, your nextTick might be the problem. As in, there is no nextTick after mounted, unless something is updated.
mounted() {
this.$nextTick(function () {
this.startMatter();
})
}
Updated based on comments.
I believe that it's this line (line 108?), which overrides your this.
let colStart = Matter.Events.on(engine, 'collisionStart', function (event) {
Try instead:
let colStart = Matter.Events.on(engine, 'collisionStart', (event) => {
Function has it own scope /this. Vue normally binds to it, however I think that doesn't work as you're in matters callback now. The arrow function ensures the scope is lexical.
Same goes for:
let colEnd = Matter.Events.on(engine, 'collisionEnd', function (event) {,
change it to:
let colEnd = Matter.Events.on(engine, 'collisionEnd', (event) => {

How to connect 2 objects using a line using konvajs in vuejs?

Good morning, I find myself working with the Konvajs library, https://github.com/konvajs/vue-konva
There is the following documentation: https://konvajs.org/docs/sandbox/Connected_Objects.html, but I can't implement it with vuejs
Since what I need to do is that when selecting object 1, I can drag and form the arrow and when selecting object 2, they are linked
Currently I have built the following:
<template>
<v-container>
<v-stage :config="configKonva">
<v-layer>
<v-circle :config="configCircle"></v-circle>
</v-layer>
<v-layer>
<v-circle :config="configCircleA"></v-circle>
</v-layer>
</v-stage>
</v-container>
</template>
<script>
export default {
data(){
return {
configKonva: {
width: 200,
height: 200
},
configCircle: {
x: 100,
y: 100,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true
},
configCircleA: {
x: 100,
y: 100,
radius: 70,
fill: "green",
stroke: "black",
strokeWidth: 4,
draggable: true
}
}
},
}
</script>
Visually I have only created the circles, I lack the connection of these 2 through a line
There are many ways to implement such functionality. Basically, you just need to listen to mousedown, mousemove and mouseup events to understand when to draw lines. You can also add touchstart, touchmove and touchend events to support mobile devices:
<template>
<div>
<v-stage
ref="stage"
:config="stageSize"
#mousedown="handleMouseDown"
#mouseup="handleMouseUp"
#mousemove="handleMouseMove"
>
<v-layer>
<v-line
v-for="line in connections"
:key="line.id"
:config="{
stroke: 'black',
points: line.points
}"
/>
<v-circle
v-for="target in targets"
:key="target.id"
:config="{
x: target.x,
y: target.y,
radius: 40,
stroke: 'black',
fill: 'green'
}"
/>
<v-text :config="{ text: 'Try to drag-to-connect objects'}"/>
</v-layer>
<v-layer ref="dragLayer"></v-layer>
</v-stage>
</div>
</template>
<script>
import Konva from "konva";
const width = window.innerWidth;
const height = window.innerHeight;
let vm = {};
function generateTargets() {
const circles = [];
for (var i = 0; i < 10; i++) {
circles.push({
x: width * Math.random(),
y: height * Math.random(),
id: i
});
}
return circles;
}
export default {
data() {
return {
stageSize: {
width: width,
height: height
},
targets: generateTargets(),
connections: [],
drawningLine: false
};
},
methods: {
handleMouseDown(e) {
const onCircle = e.target instanceof Konva.Circle;
if (!onCircle) {
return;
}
this.drawningLine = true;
this.connections.push({
id: Date.now(),
points: [e.target.x(), e.target.y()]
});
},
handleMouseMove(e) {
if (!this.drawningLine) {
return;
}
const pos = e.target.getStage().getPointerPosition();
const lastLine = this.connections[this.connections.length - 1];
lastLine.points = [lastLine.points[0], lastLine.points[1], pos.x, pos.y];
},
handleMouseUp(e) {
const onCircle = e.target instanceof Konva.Circle;
if (!onCircle) {
return;
}
this.drawningLine = false;
const lastLine = this.connections[this.connections.length - 1];
lastLine.points = [
lastLine.points[0],
lastLine.points[1],
e.target.x(),
e.target.y()
];
}
}
};
</script>
DEmo: https://codesandbox.io/s/vue-konva-connection-objects-qk2ps

add Searchbox to polygon drawing google map

I am using this below script to draw polygon to google map, which is working ok. I want to add searchbox to map. I tried a lot, But cannot embed searchbox.
http://bl.ocks.org/knownasilya/89a32e572989f0aff1f8
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<title>Drawing Tools</title>
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false&libraries=drawing"></script>
<style type="text/css">
#map, html, body {
padding: 0;
margin: 0;
width: 960px;
height: 700px;
}
#panel {
width: 200px;
font-family: Arial, sans-serif;
font-size: 13px;
float: right;
margin: 10px;
}
#color-palette {
clear: both;
}
.color-button {
width: 14px;
height: 14px;
font-size: 0;
margin: 2px;
float: left;
cursor: pointer;
}
#delete-button {
margin-top: 5px;
}
</style>
<script type="text/javascript">
var drawingManager;
var selectedShape;
var colors = ['#1E90FF', '#FF1493', '#32CD32', '#FF8C00', '#4B0082'];
var selectedColor;
var colorButtons = {};
function clearSelection () {
if (selectedShape) {
if (selectedShape.type !== 'marker') {
selectedShape.setEditable(false);
}
selectedShape = null;
}
}
function setSelection (shape) {
if (shape.type !== 'marker') {
clearSelection();
shape.setEditable(true);
selectColor(shape.get('fillColor') || shape.get('strokeColor'));
}
selectedShape = shape;
}
function deleteSelectedShape () {
if (selectedShape) {
selectedShape.setMap(null);
}
}
function selectColor (color) {
selectedColor = color;
for (var i = 0; i < colors.length; ++i) {
var currColor = colors[i];
colorButtons[currColor].style.border = currColor == color ? '2px solid #789' : '2px solid #fff';
}
// Retrieves the current options from the drawing manager and replaces the
// stroke or fill color as appropriate.
var polylineOptions = drawingManager.get('polylineOptions');
polylineOptions.strokeColor = color;
drawingManager.set('polylineOptions', polylineOptions);
var rectangleOptions = drawingManager.get('rectangleOptions');
rectangleOptions.fillColor = color;
drawingManager.set('rectangleOptions', rectangleOptions);
var circleOptions = drawingManager.get('circleOptions');
circleOptions.fillColor = color;
drawingManager.set('circleOptions', circleOptions);
var polygonOptions = drawingManager.get('polygonOptions');
polygonOptions.fillColor = color;
drawingManager.set('polygonOptions', polygonOptions);
}
function setSelectedShapeColor (color) {
if (selectedShape) {
if (selectedShape.type == google.maps.drawing.OverlayType.POLYLINE) {
selectedShape.set('strokeColor', color);
} else {
selectedShape.set('fillColor', color);
}
}
}
function makeColorButton (color) {
var button = document.createElement('span');
button.className = 'color-button';
button.style.backgroundColor = color;
google.maps.event.addDomListener(button, 'click', function () {
selectColor(color);
setSelectedShapeColor(color);
});
return button;
}
function buildColorPalette () {
var colorPalette = document.getElementById('color-palette');
for (var i = 0; i < colors.length; ++i) {
var currColor = colors[i];
var colorButton = makeColorButton(currColor);
colorPalette.appendChild(colorButton);
colorButtons[currColor] = colorButton;
}
selectColor(colors[0]);
}
function initialize () {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 16,
center: new google.maps.LatLng(52.25097, 20.97114),
mapTypeId: google.maps.MapTypeId.SATELLITE,
disableDefaultUI: true,
zoomControl: true
});
var polyOptions = {
strokeWeight: 0,
fillOpacity: 0.45,
editable: true,
draggable: true
};
// Creates a drawing manager attached to the map that allows the user to draw
// markers, lines, and shapes.
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
markerOptions: {
draggable: true
},
polylineOptions: {
editable: true,
draggable: true
},
rectangleOptions: polyOptions,
circleOptions: polyOptions,
polygonOptions: polyOptions,
map: map
});
google.maps.event.addListener(drawingManager, 'overlaycomplete', function (e) {
var newShape = e.overlay;
newShape.type = e.type;
if (e.type !== google.maps.drawing.OverlayType.MARKER) {
// Switch back to non-drawing mode after drawing a shape.
drawingManager.setDrawingMode(null);
// Add an event listener that selects the newly-drawn shape when the user
// mouses down on it.
google.maps.event.addListener(newShape, 'click', function (e) {
if (e.vertex !== undefined) {
if (newShape.type === google.maps.drawing.OverlayType.POLYGON) {
var path = newShape.getPaths().getAt(e.path);
path.removeAt(e.vertex);
if (path.length < 3) {
newShape.setMap(null);
}
}
if (newShape.type === google.maps.drawing.OverlayType.POLYLINE) {
var path = newShape.getPath();
path.removeAt(e.vertex);
if (path.length < 2) {
newShape.setMap(null);
}
}
}
setSelection(newShape);
});
setSelection(newShape);
}
else {
google.maps.event.addListener(newShape, 'click', function (e) {
setSelection(newShape);
});
setSelection(newShape);
}
});
// Clear the current selection when the drawing mode is changed, or when the
// map is clicked.
google.maps.event.addListener(drawingManager, 'drawingmode_changed', clearSelection);
google.maps.event.addListener(map, 'click', clearSelection);
google.maps.event.addDomListener(document.getElementById('delete-button'), 'click', deleteSelectedShape);
buildColorPalette();
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="panel">
<div id="color-palette"></div>
<div>
<button id="delete-button">Delete Selected Shape</button>
</div>
</div>
<div id="map"></div>
</body>
</html>
I want to add searchbox with this script, After trying a lot I posted it. thank you for your precious time.
From the SearchBox example in the documentation
add the following code to your initialize function (be sure to include the places library in the API include):
// Create the search box and link it to the UI element.
var input = document.getElementById('pac-input');
var searchBox = new google.maps.places.SearchBox(input);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
// Bias the SearchBox results towards current map's viewport.
map.addListener('bounds_changed', function() {
searchBox.setBounds(map.getBounds());
});
var markers = [];
// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener('places_changed', function() {
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
// Clear out the old markers.
markers.forEach(function(marker) {
marker.setMap(null);
});
markers = [];
// For each place, get the icon, name and location.
var bounds = new google.maps.LatLngBounds();
places.forEach(function(place) {
if (!place.geometry) {
console.log("Returned place contains no geometry");
return;
}
var icon = {
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
};
// Create a marker for each place.
markers.push(new google.maps.Marker({
map: map,
icon: icon,
title: place.name,
position: place.geometry.location
}));
if (place.geometry.viewport) {
// Only geocodes have viewport.
bounds.union(place.geometry.viewport);
} else {
bounds.extend(place.geometry.location);
}
});
map.fitBounds(bounds);
});
proof of concept fiddle
code snippet:
var drawingManager;
var selectedShape;
var colors = ['#1E90FF', '#FF1493', '#32CD32', '#FF8C00', '#4B0082'];
var selectedColor;
var colorButtons = {};
function clearSelection() {
if (selectedShape) {
if (selectedShape.type !== 'marker') {
selectedShape.setEditable(false);
}
selectedShape = null;
}
}
function setSelection(shape) {
if (shape.type !== 'marker') {
clearSelection();
shape.setEditable(true);
selectColor(shape.get('fillColor') || shape.get('strokeColor'));
}
selectedShape = shape;
}
function deleteSelectedShape() {
if (selectedShape) {
selectedShape.setMap(null);
}
}
function selectColor(color) {
selectedColor = color;
for (var i = 0; i < colors.length; ++i) {
var currColor = colors[i];
colorButtons[currColor].style.border = currColor == color ? '2px solid #789' : '2px solid #fff';
}
// Retrieves the current options from the drawing manager and replaces the
// stroke or fill color as appropriate.
var polylineOptions = drawingManager.get('polylineOptions');
polylineOptions.strokeColor = color;
drawingManager.set('polylineOptions', polylineOptions);
var rectangleOptions = drawingManager.get('rectangleOptions');
rectangleOptions.fillColor = color;
drawingManager.set('rectangleOptions', rectangleOptions);
var circleOptions = drawingManager.get('circleOptions');
circleOptions.fillColor = color;
drawingManager.set('circleOptions', circleOptions);
var polygonOptions = drawingManager.get('polygonOptions');
polygonOptions.fillColor = color;
drawingManager.set('polygonOptions', polygonOptions);
}
function setSelectedShapeColor(color) {
if (selectedShape) {
if (selectedShape.type == google.maps.drawing.OverlayType.POLYLINE) {
selectedShape.set('strokeColor', color);
} else {
selectedShape.set('fillColor', color);
}
}
}
function makeColorButton(color) {
var button = document.createElement('span');
button.className = 'color-button';
button.style.backgroundColor = color;
google.maps.event.addDomListener(button, 'click', function() {
selectColor(color);
setSelectedShapeColor(color);
});
return button;
}
function buildColorPalette() {
var colorPalette = document.getElementById('color-palette');
for (var i = 0; i < colors.length; ++i) {
var currColor = colors[i];
var colorButton = makeColorButton(currColor);
colorPalette.appendChild(colorButton);
colorButtons[currColor] = colorButton;
}
selectColor(colors[0]);
}
function initialize() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 16,
center: new google.maps.LatLng(52.25097, 20.97114),
mapTypeId: google.maps.MapTypeId.SATELLITE,
disableDefaultUI: true,
zoomControl: true
});
var polyOptions = {
strokeWeight: 0,
fillOpacity: 0.45,
editable: true,
draggable: true
};
// Creates a drawing manager attached to the map that allows the user to draw
// markers, lines, and shapes.
drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.POLYGON,
markerOptions: {
draggable: true
},
polylineOptions: {
editable: true,
draggable: true
},
rectangleOptions: polyOptions,
circleOptions: polyOptions,
polygonOptions: polyOptions,
map: map
});
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
var newShape = e.overlay;
newShape.type = e.type;
if (e.type !== google.maps.drawing.OverlayType.MARKER) {
// Switch back to non-drawing mode after drawing a shape.
drawingManager.setDrawingMode(null);
// Add an event listener that selects the newly-drawn shape when the user
// mouses down on it.
google.maps.event.addListener(newShape, 'click', function(e) {
if (e.vertex !== undefined) {
if (newShape.type === google.maps.drawing.OverlayType.POLYGON) {
var path = newShape.getPaths().getAt(e.path);
path.removeAt(e.vertex);
if (path.length < 3) {
newShape.setMap(null);
}
}
if (newShape.type === google.maps.drawing.OverlayType.POLYLINE) {
var path = newShape.getPath();
path.removeAt(e.vertex);
if (path.length < 2) {
newShape.setMap(null);
}
}
}
setSelection(newShape);
});
setSelection(newShape);
} else {
google.maps.event.addListener(newShape, 'click', function(e) {
setSelection(newShape);
});
setSelection(newShape);
}
});
// Clear the current selection when the drawing mode is changed, or when the
// map is clicked.
google.maps.event.addListener(drawingManager, 'drawingmode_changed', clearSelection);
google.maps.event.addListener(map, 'click', clearSelection);
google.maps.event.addDomListener(document.getElementById('delete-button'), 'click', deleteSelectedShape);
buildColorPalette();
// SearchBox code
// Create the search box and link it to the UI element.
var input = document.getElementById('pac-input');
var searchBox = new google.maps.places.SearchBox(input);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
// Bias the SearchBox results towards current map's viewport.
map.addListener('bounds_changed', function() {
searchBox.setBounds(map.getBounds());
});
var markers = [];
// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener('places_changed', function() {
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
// Clear out the old markers.
markers.forEach(function(marker) {
marker.setMap(null);
});
markers = [];
// For each place, get the icon, name and location.
var bounds = new google.maps.LatLngBounds();
places.forEach(function(place) {
if (!place.geometry) {
console.log("Returned place contains no geometry");
return;
}
var icon = {
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
};
// Create a marker for each place.
markers.push(new google.maps.Marker({
map: map,
icon: icon,
title: place.name,
position: place.geometry.location
}));
if (place.geometry.viewport) {
// Only geocodes have viewport.
bounds.union(place.geometry.viewport);
} else {
bounds.extend(place.geometry.location);
}
});
map.fitBounds(bounds);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
#map,
html,
body {
padding: 0;
margin: 0;
width: 960px;
height: 700px;
}
#panel {
width: 200px;
font-family: Arial, sans-serif;
font-size: 13px;
float: right;
margin: 10px;
}
#color-palette {
clear: both;
}
.color-button {
width: 14px;
height: 14px;
font-size: 0;
margin: 2px;
float: left;
cursor: pointer;
}
#delete-button {
margin-top: 5px;
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry,places,drawing&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<input id="pac-input" class="controls" type="text" placeholder="Search Box">
<div id="panel">
<div id="color-palette"></div>
<div>
<button id="delete-button">Delete Selected Shape</button>
</div>
</div>
<div id="map"></div>

Embedding mapbox-gl object in Vue page?

I want to embed a mapbox-gl map in my Vue page. How do I get it to create the new object and attach it to the DOM? I need to create the new mapboxgl.Map() object and associate it with the DOM element.
Thanks!
My code:
<template>
<div id="map">
</div>
</template>
<script>
export default {
head () {
return {
script: [
{ src: 'https://cdn.klokantech.com/mapbox-gl-js/v0.43.0/mapbox-gl.js' }
],
link: [
{ rel: 'stylesheet',
href: "https://cdn.klokantech.com/mapbox-gl-js/v0.43.0/mapbox-gl.css" }
]
}
},
map () {
return new mapboxgl.Map({
container: 'map',
center: [10.18440, -0],
zoom: 0.89,
interactive: false,
attributionControl:false
});
}
}
</script>
<style>
#map {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 0;
}
</style>
Have you try on mounted event ?
export default {
head () {
...
},
methods: {
map: function () {
mapboxgl.accessToken = '<your access token here>'; // optional
return new mapboxgl.Map({
container: 'map',
center: [10.18440, -0],
zoom: 0.89,
interactive: false,
attributionControl:false,
// set your own style:
style: 'http://osm-liberty.lukasmartinelli.ch/style.json' // free
//style: 'mapbox://styles/mapbox/streets-v9'// access token required
});
}
},
mounted () {
let map = this.map()
map.addControl(new mapboxgl.NavigationControl());
}
}
it works fine ^^