Using component to read barcodes via CDN - vue.js

I would like to install in a component via CDN called vue-cc-quaggajs to read barcodes.
I've tried the following:
new Vue({
el: "#app",
data: {
readerSize: {
width: 640,
height: 480
}
},
methods: {
logIt (data) {
console.log('detected', data)
}
},
components: {
//QuaggaScanner
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#carloscgo/vue-cc-quaggajs#2.0.0/dist/vue-quagga.js"></script>
<div id="app">
<quagga-scanner :onDetected="logIt" :readerSize="readerSize" :readerType="'ean_reader'"></quagga-scanner>
</div>
But I'm getting some errors, like:
Cannot read property 'width' of undefined" found in Scanner - Root
Could you help me? I don't know if I'm referencing the right JS file or if I could use another component to scan barcodes.

I have succeeded with quagga-scanner by building the component with CDN. It works as the default package. Here is the live demo. I worked with this image and it gives me output at console.log.
Note: Use a good camera to read the barcode. Stackoverflow snippet will not work as you don't get the camera permission from the snippet.
Vue.component('quagga-scanner', {
props: {
onDetected: {
type: Function,
},
onProcessed: {
type: Function,
},
readerType: {
type: String,
default: 'code_128_reader',
},
readerSize: {
width: {
type: Number,
default: 640,
},
height: {
type: Number,
default: 480,
}
}
},
data() {
return {
quaggaState: {
inputStream: {
type: 'LiveStream',
constraints: {
width: {
min: this.readerSize.width
},
height: {
min: this.readerSize.height
},
facingMode: 'environment',
aspectRatio: {
min: 1,
max: 2
}
}
},
locator: {
patchSize: 'medium',
halfSample: true
},
numOfWorkers: 4,
frequency: 10,
decoder: {
readers: [{
format: this.readerType,
config: {}
}]
},
locate: true
},
}
},
mounted() {
this.init();
},
methods: {
init() {
Quagga.init(this.quaggaState, function(err) {
if (err) {
return console.log(err);
}
Quagga.start();
});
Quagga.onDetected(this.onDetected ? this.onDetected : this._onDetected);
Quagga.onProcessed(this.onProcessed ? this.onProcessed : this._onProcessed);
},
reInit() {
Quagga.stop();
this.init();
},
getImage() {
const canvas = Quagga.canvas.dom.image;
return canvas.toDataURL();
},
_onProcessed(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: "green",
lineWidth: 2
});
});
}
if (result.box) {
Quagga.ImageDebug.drawPath(result.box, {
x: 0,
y: 1
}, drawingCtx, {
color: "#00F",
lineWidth: 2
});
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(result.line, {
x: 'x',
y: 'y'
}, drawingCtx, {
color: 'red',
lineWidth: 3
});
}
}
},
_onDetected(result) {
console.log('detected: ', result);
},
},
template: `
<div id="interactive" class="viewport scanner">
<video></video>
<canvas class="drawingBuffer"></canvas>
</div>
`
})
new Vue({
el: "#app",
data: {
readerSize: {
width: 640,
height: 480
}
},
methods: {
logIt(data) {
console.log('detected', data)
},
}
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* In order to place the tracking correctly */
canvas.drawing,
canvas.drawingBuffer {
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#carloscgo/vue-cc-quaggajs#2.0.0/dist/vue-quagga.js"></script>
<script src="https://cdn.rawgit.com/serratus/quaggaJS/0420d5e0/dist/quagga.min.js"></script>
<div id="app">
<quagga-scanner :on-detected="logIt" :reader-size="readerSize" :reader-type="'ean_reader'"></quagga-scanner>
</div>
</body>
</html>

Related

usin javascript 4.15 api unable to creating featurelayer using geojson collection feature from webapi core 3.1 rest

Please note that I was able to consume the geojson data and create a layer on leaflet map with ease. Also, tried using lib arcgis-to-geojson-utils but not able to get it working.
Here is my code.
Your help is greatly appreciated.
view.when()
.then(fetchData)
.then(createGraphics)
.then(createLayer)
.then(addToView)
.catch(function(e) {
console.error("Creating FeatureLayer failed", e);
})
function fetchData() {
return fetch(url,options)
.then(response => {
return response.json()
});
}
function createGraphics(schoolsGeoData) {
const geoData = JSON.parse(schoolsGeoData);
return geoData.features.map((school, i) => {
let schoolAttr = {
OBJECTID: school.properties["id"],
name: school.properties["name"]
}
return new Graphic({
// type: "point",
attributes: schoolAttr,
geometry: new Point({
x: school.geometry.coordinates[0],
y: school.geometry.coordinates[1]
}),
});
})
}
function createLayer(graphics) {
return new FeatureLayer({
source: graphics,
objectIdField: "OBJECTID",
fields: schoolFeilds(),
popupTemplate: schoolTemplate(),
renderer: myRenderer(),
geometryType: "point" ,
spatialReference: {
wkid: 4326
},
});
}
function addToView(layer) {
if(layer) {
view.map.add(layer);
}
}
Your code have a reasonable logic, of course there are thing missing that I can not know it they are working. For example, I don't know what options you add to fetch operation, but by default it will get you the data correctly, and you do not have to convert to JSON because it realize that.
I was actually going to ask you for more code, or what exactly was your problem, but I decide to remind you that you actually have a specific layer to handle GeoJSON data, GeoJSONLayer.
ArcGIS API - GeoJSONLayer
ArcGIS Examples - GeoJSONLayer
But, anyway I will leave you here a running example of what you are trying to do, fetching the data and using FeatureLayer, using the data from the example I mention,
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>GeoJSON with FeatureLayer - 4.15</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.15/esri/themes/light/main.css"
/>
<script src="https://js.arcgis.com/4.15/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"esri/Graphic"
], function(Map, MapView, FeatureLayer, Graphic) {
const map = new Map({
basemap: "gray"
});
const view = new MapView({
center: [-80, 35],
zoom: 8,
map,
container: "viewDiv"
});
view.when()
.then(fetchData)
.then(createGraphics)
.then(createLayer)
.then(addToView)
.catch(function(e) {
console.error("Creating FeatureLayer failed", e);
})
function fetchData() {
return fetch(
'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson'
)
.then(response => {
return response.json()
});
}
function createGraphics(data) {
// const geoData = JSON.parse(data);
return data.features.map((feature, i) => {
return new Graphic({
attributes: {
OBJECTID: i,
title: feature.properties["title"],
mag: feature.properties["mag"],
type: feature.properties["type"],
place: feature.properties["place"],
time: feature.properties["time"]
},
geometry: {
type: "point",
x: feature.geometry.coordinates[0],
y: feature.geometry.coordinates[1]
},
});
})
}
function createLayer(graphics) {
const popupTemplate = {
title: "{title}",
content: "Magnitude {mag} {type} hit {place} on {time}",
fieldInfos: [
{
fieldName: "time",
format: {
dateFormat: "short-date-short-time"
}
}
],
outFields: ["title", "mag", "type", "place", "time"]
}
const renderer = {
type: "simple",
field: "mag",
symbol: {
type: "simple-marker",
color: "orange",
outline: {
color: "white"
}
},
visualVariables: [
{
type: "size",
field: "mag",
stops: [
{
value: 2.5,
size: "10px"
},
{
value: 8,
size: "40px"
}
]
}
]
};
return new FeatureLayer({
source: graphics,
fields: [{
name: "OBJECTID",
alias: "ObjectID",
type: "oid"
}, {
name: "title",
alias: "Title",
type: "string"
}
, {
name: "mag",
alias: "Magnitude",
type: "double"
}
, {
name: "type",
alias: "Type",
type: "string"
}, {
name: "place",
alias: "Place",
type: "string"
}, {
name: "time",
alias: "Time",
type: "date"
}],
objectIdField: "OBJECTID",
popupTemplate,
renderer
});
}
function addToView(layer) {
if(layer) {
view.map.add(layer);
}
}
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>

"Setting a `style` bypass at element creation is deprecated" when specifying style along with data for a node

Using cytoscape.js, I am setting the style of a node while defining it.
Shortened example below:
window.addEventListener('DOMContentLoaded', function(){
var cy = window.cy = cytoscape({
elements: {
nodes: [
{ data: { id: 'a', name: 'apple' }, style: { 'background-color': 'darkgreen' } },
]
}
});
});
(I have a default style for a node that is a different color)
This works fine, but when I run my code, the browser console shows the following warning:
Setting a `style` bypass at element creation is deprecated
What does it mean and what is the correct (non-deprecated) way to set it?
Thank you in advance!
The correct way of doing this would be to use the cytoscape stylesheet, as can be seen in every example in the docs:
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
boxSelectionEnabled: false,
autounselectify: true,
style: [{
selector: "node",
css: {
"label": "data(id)",
"text-valign": "center",
"text-halign": "center",
"background-color": "data(color)"
}
},
{
selector: "edge",
css: {
"line-fill": "radial-gradient",
"line-gradient-stop-colors": "red green blue",
"line-gradient-stop-positions": "25 50 75"
}
}
],
elements: {
nodes: [{
data: {
id: "a",
color: "#2763c4"
}
},
{
data: {
id: "b",
color: "#37a32d"
}
},
{
data: {
id: "c",
color: "#37a32d"
}
}
],
edges: [{
data: {
source: "a",
target: "b"
}
},
{
data: {
source: "a",
target: "c"
}
}
]
},
layout: {
name: "dagre"
}
}));
cy.ready(function() {
cy.dblclick();
});
var nid = 0;
cy.bind('dblclick', function(evt) {
console.log('dblclick');
cy.add({
group: 'nodes',
data: {
id: nid,
faveColor: 'red'
},
position: {
x: evt.x,
y: evt.y
}
});
nid++;
});
cy.bind('click', 'node', function(evt) {
console.log('node clicked: ', evt.target.id());
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
float: right;
position: absolute;
}
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://unpkg.com/cytoscape#3.3.0/dist/cytoscape.min.js">
</script>
<!-- cyposcape dagre -->
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
<script src="https://unpkg.com/cytoscape-dblclick/dist/index.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

Cytoscape js - Call a function whenever a node is clicked

I initialized the cytoscape like this:
var cy = cytoscape({
container: document.getElementById('cy'),
elements: [
{ data: { id: 'a' } },
{ data: { id: 'b' } },
{ data: { id: 'c' } },
{
data: {
id: 'ab',
source: 'a',
target: 'b'
}
},
{
data: {
id: 'ac',
source: 'a',
target: 'c'
}
}
]
});
Then I added a function which adds a new node whenever the user double clicks on the viewport.
var nid = 1;
document.getElementById("cy").ondblclick = function(e) {
cy.add({ data: { id: nid }, renderedPosition: { x: e.x, y: e.y } });
nid++;
};
Then I wrote this function which should be called whenever user clicks a node. It works whenever user clicks on a node which I added manually when initializing the cytoscape but the problem is its not working for the nodes which user added by double clicking.
cy.$('node').on('click', function (e) {
console.log('node clicked: ', e.target.id());
});
Any idea what am I doing wrong?
I have a working version of your code here:
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
boxSelectionEnabled: false,
autounselectify: true,
style: [{
selector: "node",
css: {
"label": "data(id)",
"text-valign": "center",
"text-halign": "center",
"background-color": "data(faveColor)"
}
},
{
selector: "edge",
css: {
"curve-style": "bezier",
"control-point-step-size": 40,
"target-arrow-shape": "triangle"
}
}
],
elements: {
nodes: [{
data: {
id: "a",
faveColor: "#2763c4"
}
},
{
data: {
id: "b",
faveColor: "#37a32d"
}
},
{
data: {
id: "c",
faveColor: "#37a32d"
}
}
],
edges: [{
data: {
source: "a",
target: "b"
}
},
{
data: {
source: "a",
target: "c"
}
}
]
},
layout: {
name: "dagre"
}
}));
cy.ready(function() {
cy.dblclick();
});
var nid = 0;
cy.bind('dblclick', function(evt) {
cy.add({
group: 'nodes',
data: {
id: nid,
faveColor: 'red'
},
position: {
x: evt.x,
y: evt.y
}
});
nid++;
});
cy.bind('click', 'node', function(evt) {
console.log('node clicked: ', evt.target.id());
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
float: right;
position: absolute;
}
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://unpkg.com/cytoscape#3.3.0/dist/cytoscape.min.js">
</script>
<!-- cyposcape dagre -->
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
<script src="https://unpkg.com/cytoscape-dblclick/dist/index.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
I used the cy.on()/cy.bind() method, that seems to work with newly added nodes :)

With cytoscape.js how to automatically expand the height of the container of a graph?

Is it possible to automatically expand the height of the container of a graph, according to the size of the graph?
I want to display lots of graphs of different sizes on a web page, without having to specify the height of each DOM container.
Does it make sense?
Answer:
It is not the best solution to change anything regarding the container of cytoscape.
Alternative for you:
It is far better to work with the padding of the graph in order to display the graph in a dynamic/suitable way. The easiest way to do that, is to add your nodes and run your layout and then, when the layout is loaded, you can call cy.fit(cy.elements(), yourPadding).
In cytoscape, padding is handled exactly the same way as in css, so you just calculate (based on the number of nodes maybe?) the appropriate padding for your graph and fit it to the viewport.
Additionally, you can always wrap things up with a slick ease-in animation to top things off.
Code:
Snippet works when you click on edit the above snippet and run it in the snippet editor, here the function does not work due to the size limitation and I can't be bothered to adjust it without seeing the outcome in the editor.
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
boxSelectionEnabled: false,
autounselectify: true,
style: [
{
selector: "node",
css: {
content: "data(id)",
"text-valign": "bottom",
"text-halign": "center",
height: "60px",
width: "60px",
"border-color": "black",
"border-opacity": "1",
"background-image":
"https://farm8.staticflickr.com/7272/7633179468_3e19e45a0c_b.jpg"
}
},
{
selector: "edge",
css: {
"target-arrow-shape": "triangle"
}
},
{
selector: ":selected",
css: {
"background-color": "black",
"line-color": "black",
"target-arrow-color": "black",
"source-arrow-color": "black"
}
}
],
elements: {
nodes: [
{ data: { id: "n0" } },
{ data: { id: "n1" } },
{ data: { id: "n2" } },
{ data: { id: "n3" } },
{ data: { id: "n4" } },
{ data: { id: "n5" } },
{ data: { id: "n6" } },
{ data: { id: "n7" } },
{ data: { id: "n8" } },
{ data: { id: "n9" } },
{ data: { id: "n10" } },
{ data: { id: "n11" } },
{ data: { id: "n12" } },
{ data: { id: "n13" } },
{ data: { id: "n14" } },
{ data: { id: "n15" } },
{ data: { id: "n16" } }
],
edges: [
{ data: { source: "n0", target: "n1" } },
{ data: { source: "n1", target: "n2" } },
{ data: { source: "n1", target: "n3" } },
{ data: { source: "n2", target: "n7" } },
{ data: { source: "n2", target: "n11" } },
{ data: { source: "n2", target: "n16" } },
{ data: { source: "n3", target: "n4" } },
{ data: { source: "n3", target: "n16" } },
{ data: { source: "n4", target: "n5" } },
{ data: { source: "n4", target: "n6" } },
{ data: { source: "n6", target: "n8" } },
{ data: { source: "n8", target: "n9" } },
{ data: { source: "n8", target: "n10" } },
{ data: { source: "n11", target: "n12" } },
{ data: { source: "n12", target: "n13" } },
{ data: { source: "n13", target: "n14" } },
{ data: { source: "n13", target: "n15" } }
]
},
layout: {
name: "dagre",
padding: 5
}
}));
cy.unbind("click");
cy.bind("click", "node", function(event) { // just for demonstration purposes here
var coll = cy.$(event.target).successors(); // get all outgoing nodes
coll = coll.add(event.target); // add their source
var removed = cy.remove(cy.elements().not(coll)); // remove all other elements
var len = cy.nodes().length;
var pad = (len < 10 ? (len < 5 ? (len < 3 ? (len < 2 ? 150 : 100 ) : 75 ) : 50 ) : 25); // custom padding function here
cy.animate({
fit: {
eles: cy.elements(),
padding: pad
}
}, {
duration: 500,
easing: 'ease-in'
});
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
float: left;
}
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.17/cytoscape.min.js"></script>
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.js"></script>
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

Drilldown in Map with Vue.js

I'm trying to use the Drilldown in Map (vue-Highchart), but cannot get it working.
like this: https://www.highcharts.com/maps/demo/map-drilldown
Anyone have any examples of this in Vue.js? Please.
Tks.
Here is simple example of drilldown functionality(with vue-highcharts) which provides drilldown and drillup event from Vue-instance:
Vue.use(VueHighcharts, { Highcharts: Highcharts });
// helper script to load external script
let loadScript = function(url, onLoad){
var scriptTag = document.createElement('script');
scriptTag.src = url;
scriptTag.onload = onLoad;
scriptTag.onreadystatechange = onLoad;
document.body.appendChild(scriptTag);
};
// simple chart options
var options = {
chart: {},
title: {
text: 'Highcharts-Vue Map Drilldown Example'
},
subtitle: {
text: '',
floating: true,
align: 'right',
y: 50,
style: {
fontSize: '16px'
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
colorAxis: {
min: 0,
minColor: '#E6E7E8',
maxColor: '#005645'
},
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
plotOptions: {
map: {
states: {
hover: {
color: '#EEDD66'
}
}
}
},
drilldown: {
activeDataLabelStyle: {
color: '#FFFFFF',
textDecoration: 'none',
textOutline: '1px #000000'
},
drillUpButton: {
relativeTo: 'plotBox',
position: {
x: 70,
y: 280
}
}
},
series: [{
data: Highcharts.geojson(Highcharts.maps['countries/us/us-all']).map((d, i) => {
d.drilldown = true;
// set value just for example
d.value = i;
return d;
}),
name: 'USA',
dataLabels: {
enabled: true,
format: '{point.properties.postal-code}'
}
}]
};
let vm = new Vue({
el: '#app',
data: {
isLoading: false,
options: options
},
created() {
// prepare events for chart from Vue instance
this.options.chart.events = {
drilldown: this.drilldown.bind(this),
drillup: this.drillup.bind(this)
}
},
methods: {
drilldown(e) {
let { chart } = this.$refs.highcharts;
if (!e.seriesOptions) {
mapKey = 'countries/us/' + e.point.properties['hc-key'] + '-all';
if (Highcharts.maps[mapKey]) {
this.prepareDrilldownData(mapKey, e.point);
return;
}
this.isLoading = true;
loadScript('https://code.highcharts.com/mapdata/' + mapKey + '.js', () => {
this.isLoading = false;
this.prepareDrilldownData(mapKey, e.point);
});
}
chart.setTitle(null, { text: e.point.name });
},
drillup(e) {
let { chart } = this.$refs.highcharts;
chart.setTitle(null, { text: '' });
},
prepareDrilldownData(mapKey, point) {
let { chart } = this.$refs.highcharts;
data = Highcharts.geojson(Highcharts.maps[mapKey]).map((d, i) => {
// set value just for example
d.value = i;
return d;
});
chart.addSeriesAsDrilldown(point, {
name: point.name,
data: data,
dataLabels: {
enabled: true,
format: '{point.name}'
}
});
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<script src="https://code.highcharts.com/maps/highmaps.js"></script>
<script src="https://code.highcharts.com/maps/modules/drilldown.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-highcharts/dist/vue-highcharts.min.js"></script>
<script src="https://code.highcharts.com/mapdata/countries/us/us-all.js"></script>
<div id="app">
<highmaps ref="highcharts" :options="options"></highmaps>
<div v-if="isLoading" style="text-align: center; margin-top: 15px; font-size: 20px;">Loading...</div>
</div>
There is also jsfiddle if you want.