I'm having trouble when initializing the position for my custom draggable directive. I was supposed to make its position on the center of the screen. However, after I calculating, it only binds on what is on the data() which is (0,0). Here is my code below:
export default {
directives: {
Drag,
},
data: function() {
return {
position: {
x: 0,
y: 0,
},
window: {
width: 0,
height: 0,
},
}
},
created() {
window.addEventListener('resize', this.handleResize)
this.handleResize()
},
destroyed() {
window.removeEventListener('resize', this.handleResize)
},
methods: {
handleResize() {
this.window.width = window.innerWidth
this.window.height = window.innerHeight
},
},
mounted: function() {
this.position.x = this.window.width / 2
this.position.y = this.window.height / 2
},
}
On HTML:
<div class="modal-wrapper" v-drag="position">
Related
I'm aiming to retrieve the full scrollable height of my page using:
document.body.scrollHeight
but all I get back is the height of the viewport and not the full height of the scrollable page.
I'm running this in a method that is called after mounted. It's even in a nexttick function. I need this to randomly place images over the full height of the page. It could be something to do with Vue's reactivity(?) and the DOM not updating quick enough for my method to get the full document height?
What is a different way I can get the scroll height of a document in Vue that will actually work?
<script>
export default {
data() {
return {
images: [
require("#/assets/img/icons/1.png"),
require("#/assets/img/icons/2.png"),
],
addedImage: [],
imgTop: 150,
imgLeft: 900,
imgHeight: 64,
imgWidth: 64,
selectedImage: "",
nextId: 100,
};
},
mounted() {
this.randomImage();
this.$nextTick(() => {
for (let i = 0; i < 40; i++) {
this.randomImage();
this.addImage();
this.randomPosition();
}
});
},
methods: {
randomImage() {
const idx = Math.floor(Math.random() * this.images.length);
this.selectedImage = this.images[idx];
},
randomPosition() {
const randomPos = (twoSizes) => Math.round(Math.random() * twoSizes);
this.imgTop = randomPos(document.body.scrollHeight - this.imgHeight);
this.imgLeft = randomPos(window.innerWidth - this.imgWidth);
},
addImage() {
this.addedImage.push({
style: {
top: `${this.imgTop}px`,
left: `${this.imgLeft}px`,
height: `${this.imgHeight}px`,
width: `${this.imgWidth}px`,
},
src: this.selectedImage,
id: this.nextId++,
});
},
},
};
</script>
I wanted to make a div of random positioned icons and this is what i made so far.
Can we make this to generate only limited number of images like 20 images and not unlimited.
If you have better way to make something like this, then i would be really thankful.
Thanks
let nextId = 20
new Vue({
el: '#app',
data() {
return {
images: [
'//placekitten.com/200/200',
'//placekitten.com/200/201',
'//placekitten.com/200/202',
'//placekitten.com/200/203',
'//placekitten.com/200/204',
],
addedImage: [],
imgTop: -100,
imgLeft: -100,
imgHeight: 64,
imgWidth: 64,
changeInterval: 10,
selectedImage: ''
}
},
created() {
this.randomImage();
const randomImg = func => setInterval(func, this.changeInterval);
randomImg(this.randomImage);
randomImg(this.addImage);
randomImg(this.randomPosition);
},
methods: {
randomImage() {
const idx = Math.floor(Math.random() * this.images.length);
this.selectedImage = this.images[idx];
},
randomPosition() {
const randomPos = twoSizes => Math.round(Math.random() * twoSizes);
this.imgTop = randomPos(window.innerHeight - this.imgHeight);
this.imgLeft = randomPos(window.innerWidth - this.imgWidth);
},
addImage(){
this.addedImage.push({
style: {
top: `${this.imgTop}px`,
left: `${this.imgLeft}px`,
height: `${this.imgHeight}px`,
width: `${this.imgWidth}px`
},
src: this.selectedImage,
id: nextId++
});
},
}
})
.image {
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<img :style="image.style" class="image" :key="image.id" :src="image.src" v-for="image in addedImage">
</div>
Introduce variables for the total, the current count, and the interval reference:
limit: 20,
counter: 0,
interval: null
Combine the three calls to setInterval into one and store the interval.
created() {
this.interval = setInterval(() => {
this.randomImage();
this.randomPosition();
this.addImage();
this.counter++;
if (this.counter === this.limit) {
clearInterval(this.interval);
}
}, this.changeInterval);
},
Each call increases the counter and when the limit is reached, the interval is cleared. Here's a demo:
let nextId = 20
new Vue({
el: '#app',
data() {
return {
images: [
'//placekitten.com/200/200',
'//placekitten.com/200/201',
'//placekitten.com/200/202',
'//placekitten.com/200/203',
'//placekitten.com/200/204',
],
addedImage: [],
imgTop: -100,
imgLeft: -100,
imgHeight: 64,
imgWidth: 64,
changeInterval: 10,
selectedImage: '',
limit: 20,
counter: 0,
interval: null
}
},
created() {
this.interval = setInterval(() => {
this.randomImage();
this.randomPosition();
this.addImage();
this.counter++;
if (this.counter === this.limit) {
clearInterval(this.interval);
}
}, this.changeInterval);
},
methods: {
randomImage() {
const idx = Math.floor(Math.random() * this.images.length);
this.selectedImage = this.images[idx];
},
randomPosition() {
const randomPos = twoSizes => Math.round(Math.random() * twoSizes);
this.imgTop = randomPos(window.innerHeight - this.imgHeight);
this.imgLeft = randomPos(window.innerWidth - this.imgWidth);
},
addImage(){
this.addedImage.push({
style: {
top: `${this.imgTop}px`,
left: `${this.imgLeft}px`,
height: `${this.imgHeight}px`,
width: `${this.imgWidth}px`
},
src: this.selectedImage,
id: nextId++
});
},
}
})
.image {
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<img :style="image.style" class="image" :key="image.id" :src="image.src" v-for="image in addedImage">
</div>
I solved this by adding a condition with a array length.
Length can be defined with any number of images we want. For example if we want 20 images then add this:
addImage(){
if (this.addedImage.length < 20) {
this.addedImage.push({
style: {
top: `${this.imgTop}vh`,
left: `${this.imgLeft}vw`,
height: `${this.imgHeight}px`,
width: `${this.imgWidth}px`
},
src: this.selectedImage,
id: nextId++
});
}
}
I am using QuaggaJs to scan the barcode. Everything is good and smooth for desktop version of scanner. But it gets broken when coming to mobile version of website and that too mainly on iPhone.
I tested in both safari and Chrome and for different phone it behaves differently. For some phone camera gets hang and for some camera didn't start at all.
Also, the canvas size is not setting up in the parent div. camera is getting outside the DOM.
Here is what I did.
HTML
<div class="scanner-box">
<div id="scanner-container" class="main_scanner"></div>
</div>
JS
$(document).ready(function(){
if($(".scanner-box").length > 0){
var canvas_width = $(".scanner-box").width();
var canvas_height = $(".scanner-box").height();
if (_scannerIsRunning) {
Quagga.stop();
} else {
startScanner(canvas_width,canvas_height);
}
}
}
var _scannerIsRunning = false;
function startScanner(canvasRatio,canvasHeight) {
Quagga.init({
inputStream: {
name: "Live",
type: "LiveStream",
target: document.querySelector('#scanner-container'),
constraints: {
width: "100%",
height: "100%",
facingMode: "environment"
},
},
decoder: {
readers: [
"ean_reader",
"ean_8_reader"
],
debug: {
showCanvas: true,
showPatches: true,
showFoundPatches: true,
showSkeleton: true,
showLabels: true,
showPatchLabels: true,
showRemainingPatchLabels: true,
boxFromPatches: {
showTransformed: true,
showTransformedBox: true,
showBB: true
}
}
},
},
function (err) {
if (err) {
$("#error").text(err);
return
}
console.log("Initialization finished. Ready to start");
Quagga.start();
_scannerIsRunning = true;
});
Quagga.onProcessed(function (result) {
var 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 });
}
}
});
Quagga.onDetected(function (result) {
var barcodeResult = $("#result").text(result.codeResult.code);
var barcode = result.codeResult.code;
if(barcode.toString().length < '13'){
}else{
checkBarCode(barcode,canvasRatio,canvasHeight);
if (_scannerIsRunning) {
Quagga.stop();
}
}
console.log("Barcode detected and processed : [" + result.codeResult.code + "]", result);
});
}
CSS
.scanner-box{width:480px;height:320px;background-color:#9a9a9a;position:relative;margin-top:10px;}
#scanner-container{position:relative;height:inherit;}
#scanner-container canvas{
position: absolute;
left : 0px;
top: 0px;
}
this css is just like the sample form https://serratus.github.io/quaggaJS/v1.0.0-beta.1/examples/file_input/
it makes the canvas area which draws windows cover the camera steam area .
I'm trying to create a snake game in Phaser 3. The arrow.(key).isDown is acting strangely and I can't figure out why. If you press a key weather it is up, down, left or right it will not change directions if you press the opposite, it just keeps moving. like if I press down it keeps going down even after I press up. I have been trying to debug it for hours. All the examples pretty much have it set up the same way.
This is my code so far
class mainScene {
preload() {
this.load.image("fruit", "images/fruit.png");
this.load.image("snake", "images/snake.png");
}
create() {
this.score = 0;
this.snake = this.physics.add.sprite(20, 20, "snake");
this.fruit = this.physics.add.sprite(
Phaser.Math.Between(10, 590),
Phaser.Math.Between(10, 590),
"fruit"
);
this.scoreText = this.add.text(500, 5, `Score: ${this.score}`);
this.arrow = this.input.keyboard.createCursorKeys();
//debug
}
update() {
if (this.physics.overlap(this.snake, this.fruit)) {
this.hit();
}
this.snake.setVelocity(0);
if (this.arrow.right.isDown) {
this.snake.setVelocityX(50);
if (this.snake.x > 600) {
this.outOfBounds();
}
} else if (this.arrow.left.isDown) {
this.snake.setVelocityX(-50);
if (this.snake.x < 0) {
this.outOfBounds();
}
}
if (this.arrow.down.isDown) {
this.snake.setVelocityY(50);
if (this.snake.y > 600) {
this.outOfBounds();
}
} else if (this.arrow.up.isDown) {
this.snake.setVelocityY(-50);
if (this.snake.y < 0) {
this.outOfBounds();
}
}
}
hit() {
this.fruit.x = Phaser.Math.Between(10, 590);
this.fruit.y = Phaser.Math.Between(10, 590);
this.score += 1;
this.scoreText.setText(`Score: ${this.score}`);
this.tweens.add({
targets: this.snake,
duration: 200,
scaleX: 1.2,
scaleY: 1.2,
yoyo: true,
});
}
outOfBounds() {
this.score = 0;
this.scoreText.setText(`Score: ${this.score}`);
this.gameOverText = this.add.text(
100,
250,
"You went out of bounds.\nGame Over\nPress Space to continue.",
{ fontSize: "24px" }
);
if (this.arrow.space.isDown) {
this.gameOverText.destroy();
this.scene.restart();
}
}
}
const config = {
type: Phaser.CANVAS,
width: 600,
height: 600,
backgroundColor: 0x000040,
scene: mainScene,
physics: {
default: "arcade",
debug: true,
setBounds: { x: 0, y: 0, width: 600, height: 600 },
},
parent: "game",
};
new Phaser.Game(config);
I am using the below code -
afterListeners: function(thisEl, eOpts) {
sliderSprite = Ext.create('Ext.draw.sprite.Rect', {
width: spriteWidth, // half year width height : 20, x : 16, y : 0, draggable : true, floatable : true, 'stroke-width' : 2, fill : '#FCE5C5', stroke : '#C6B395' });
sliderSprite.show(true);
thisEl.getSurface().add(sliderSprite);
alert("before source");
new Ext.drag.Source({
element: sliderSprite,
constrain: {
// Drag only horizontal in 30px increments
horizontal: true, // snap: { // y: 30 // }
},
onDragMove: function() {
alert("inside source");
spriteHighlighter.remove();
me.onDragSprite(e, this, chartWidth, spriteWidth);
},
onDragEnd: function() {
me.refreshCharts(xPlots, bigChart, sliderSprite, firstYear, lastYear, chartWidth);
}
});
alert("outside source");
},
}
}
Now, the issue is, control doesn't go inside the Ext.drag.Source(). I get 2 alert messages ,before source and outside source. and because it doesn't go inside Ext.drag.Source().
The drag-able functionality of the element is not working. What should I do ?
First you need to be clear on which component you want to use. After that you need to put afterrender event on that component and inside of that event you can use Ext.drag.Source.
In this FIDDLE, I have created a demo using button and Ext.drag.Source.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
var buttons = [],
rendomColor = () => {
return "#" + ((1 << 24) * Math.random() | 0).toString(16);
};
for (var i = 0; i < 10; i++) {
buttons.push({
text: `Button ${i+1}`,
margin: 10,
style: `background:${rendomColor()}`
});
}
Ext.create({
xtype: 'panel',
height: window.innerHeight,
title: 'Ext.drag.Source Example',
defaults: {
xtype: 'button'
},
items: buttons,
renderTo: Ext.getBody(),
listeners: {
afterrender: function (panel) {
panel.items.items.forEach(item => {
new Ext.drag.Source({
element: item.el,
constrain: {
// Drag only vertically in 30px increments
//vertical: true,
snap: {
y: 1,
x: 1
}
}
})
})
}
}
});
}
});