react-native requestanimationframe - flicker - freeze - app crash - react-native

am learning to build app using react-native and below is the component code that am using. The problem is - when I simulate this app - it crashes in few seconds. I couldnt understand what is causing this problem. Can someone please suggest.
I am trying to animate a canvas circle using requestAnimationFrame in this component.
Thank you ..
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Dimensions
} from 'react-native';
import Canvas from 'react-native-canvas';
export default class ThreeDiscs extends Component{
constructor(props){
super(props);
this.state = {
context: null,
screen: {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height
},
a: 0,
b: 0,
c: 100,
d: 100
};
this.coordinates = {
a: 0,
b: 0,
c: 100,
d: 100
};
this.directions = {
increment: 5,
direction: 0
};
this.discs = [
{
x: 150,
y: 250,
lastX: 150,
lastY: 250,
velocityX: -3.2,
velocityY: 3.5,
radius: 10,
innerColor: 'rgba(255,255,0,1)',
middleColor: 'rgba(255,255,0,0.7)',
outerColor: 'rgba(255,255,0,0.5)',
strokeStyle: 'gray',
}
];
this.numDiscs = this.discs.length;
}
rendercanvas = (canvas) => {
canvas.width = this.state.screen.width;
canvas.height = this.state.screen.height;
const context = canvas.getContext('2d');
this.setState({context: context});
context.fillStyle = 'purple';
context.fillRect(0,0,100,100);
this.drawBackground(context);
this.update(context);
this.draw(context);
this.animatecanvas(context);
}
drawBackground(context) {
var STEP_Y = 12,
i = this.state.screen.height;
context.strokeStyle = 'lightgray';
context.lineWidth = 0.5;
while(i > STEP_Y*4) {
context.beginPath();
context.moveTo(0, i);
context.lineTo(context.canvas.width, i);
context.stroke();
i -= STEP_Y;
}
context.save();
context.strokeStyle = 'rgba(100,0,0,0.3)';
context.lineWidth = 1;
context.beginPath();
context.moveTo(35,0);
context.lineTo(35,context.canvas.height);
context.stroke();
context.restore();
}
update(context) {
var disc = null;
for(var i=0; i < this.numDiscs; ++i) {
disc = this.discs[i];
if (disc.x + disc.velocityX + disc.radius > context.canvas.width ||
disc.x + disc.velocityX - disc.radius < 0)
disc.velocityX = -disc.velocityX;
if (disc.y + disc.velocityY + disc.radius > context.canvas.height ||
disc.y + disc.velocityY - disc.radius < 0)
disc.velocityY= -disc.velocityY;
disc.x += disc.velocityX;
disc.y += disc.velocityY;
}
}
draw(context) {
var disc = this.discs[i];
for(var i=0; i < this.numDiscs; ++i) {
disc = this.discs[i];
context.save();
context.beginPath();
context.arc(disc.x, disc.y, disc.radius, 0, Math.PI*2, false);
context.fillStyle = '#000';
context.strokeStyle = disc.strokeStyle;
context.fill();
context.stroke();
context.restore();
}
}
animatecanvas(context){
context.clearRect(0,0,this.state.screen.width,this.state.screen.height);
this.drawBackground(context);
this.update(context);
this.draw(context);
requestAnimationFrame(() => {this.animatecanvas(context)});
}
render(){
return(
<Canvas ref={this.rendercanvas} />
);
}
}

Related

Infinite draggable webgl slider

I'm new to webgl and I'm trying to imrpove this infinite draggable webgl slider:
https://codepen.io/ReGGae/pen/povjKxV
setup() {
const { ww } = store
const state = this.state
const { items, titles } = this.ui
const {
width: wrapWidth,
left: wrapDiff
} = this.el.getBoundingClientRect()
// Set bounding
state.max = -(items[items.length - 1].getBoundingClientRect().right - wrapWidth - wrapDiff)
state.min = 0
// Global timeline
this.tl = gsap.timeline({
paused: true,
defaults: {
duration: 1,
ease: 'linear'
}
})
.fromTo('.js-progress-line-2', {
scaleX: 1
}, {
scaleX: 0,
duration: 0.5,
ease: 'power3'
}, 0)
.fromTo('.js-titles', {
yPercent: 0
}, {
yPercent: -(100 - (100 / titles.length)),
}, 0)
.fromTo('.js-progress-line', {
scaleX: 0
}, {
scaleX: 1
}, 0)
// Cache stuff
for (let i = 0; i < items.length; i++) {
const el = items[i]
const { left, right, width } = el.getBoundingClientRect()
// Create webgl plane
const plane = new Plane()
plane.init(el)
// Timeline that plays when visible
const tl = gsap.timeline({ paused: true })
.fromTo(plane.mat.uniforms.uScale, {
value: 0.65
}, {
value: 1,
duration: 1,
ease: 'linear'
})
// Push to cache
this.items.push({
el, plane,
left, right, width,
min: left < ww ? (ww * 0.775) : -(ww * 0.225 - wrapWidth * 0.2),
max: left > ww ? state.max - (ww * 0.775) : state.max + (ww * 0.225 - wrapWidth * 0.2),
tl,
out: false
})
}
}
What I would like to be able to do is to perfectly loop the words with the slides. Now when dragging it fast the words don't match the pictures (currently there is one more word than the images as workaround).
Plus I would like to find a way to place links on the draggable images.
I would be very grateful for any advice.

VueJS 3 composition API lifecycle not taking onMounted into account

I'm creating a greeting card app with VueJS3. I want to download 2 images (the background and a star sprite), then showing the image with animated sprites.
If I put onMounted"at the end it doesn't work, I have this error:
[Vue warn]: onMounted is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement.
at <RouterView>
at <App>
If I put onMounted like this, it doesn't show the MOUNTED log...
<template>
<div class="board">
<canvas
id='carte'
ref='carte'
:width="size.w"
:height="size.h"
max-width="100%"
tabindex='0'
style="border:1px solid #000000;"
></canvas>
</div>
<div id="texteRemplacement" v-if="petit">
<p v-for="p in texte.split('\n')" v-bind:key="p">
{{ p }}
</p>
</div>
</template>
<script>
import {
defineComponent,
onMounted,
ref,
reactive,
nextTick,
toRefs,
watch,
} from 'vue';
import axios from 'axios';
export default defineComponent({
name: 'Visionneuse',
props: ['texteEnvoye', 'taille'],
async setup(props) {
const myCanvas = ref(null);
const carte = ref(null);
const { texteEnvoye, taille } = toRefs(props);
const texte = ref('');
const rapport = ref(0);
const petit = ref((window.innerWidth < 750));
const size = reactive({
w: window.innerWidth * taille.value,
h: window.innerHeight * taille.value,
});
const tailleFond = reactive({
w: 0,
h: 0,
});
let fpsInterval;
let startTime;
let now;
let then;
let elapsed;
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
function genererEtoile() {
return ({
taille: getRandomInt(10) + 10,
position: {
x: Math.random(),
y: Math.random(),
},
deviation: {
x: {
valeur: getRandomInt(18) - 9,
sens: 1,
amplitude: 5 + getRandomInt(5),
},
y: {
valeur: getRandomInt(8) - 4,
sens: 1,
amplitude: 5 + getRandomInt(5),
},
},
grossissement: {
valeur: getRandomInt(5) - 3,
sens: 1,
},
});
}
const etoiles = ref(new Array(50).fill(null).map(() => (genererEtoile())));
const date = ref([
{
valeur: {
chiffre: '2',
position: 0,
sens: 1,
},
},
{
valeur: {
chiffre: '0',
position: 3,
sens: -1,
},
},
{
valeur: {
chiffre: '2',
position: -3,
sens: 1,
},
},
{
valeur: {
chiffre: '1',
position: -3,
sens: -1,
},
},
]);
function drawText() {
const fontSize = 0.05 * size.w - 10;
myCanvas.value.font = `${fontSize}px Caviar Dream`;
myCanvas.value.textAlign = 'center';
myCanvas.value.fillStyle = 'white';
myCanvas.value.strokeStyle = 'black';
myCanvas.value.lineWidth = 0.006 * size.w - 10;
const x = (size.w * 9) / 13;
const y = (size.h * 5) / 7;
const lineHeight = fontSize;
const lines = texte.value.split('\n');
for (let i = 0; i < lines.length; i += 1) {
myCanvas.value.fillText(
lines[lines.length - i - 1],
x,
y + ((lines.length - 1) * lineHeight) / 2 - (i * lineHeight),
);
// myCanvas.value.strokeText(
// lines[lines.length - i - 1],
// x,
// y + ((lines.length - 1) * lineHeight) / 2 - (i * lineHeight),
// );
}
}
watch(texteEnvoye, (x) => {
texte.value = x;
// requestAnimationFrame(initCarte);
});
onMounted(() => {
console.log('MOUNTED');
const c = carte.value;
const ctx = c.getContext('2d');
myCanvas.value = ctx;
// requestAnimationFrame(initCarte);
// eslint-disable-next-line
startAnimating(20);
});
async function getImage(chemin) {
await axios.get(`${process.env.VUE_APP_PUBLICPATH}img/${chemin}`, { responseType: 'arraybuffer' })
.then((res) => {
console.log(`data:${res.headers['content-type']};base64,${btoa(String.fromCharCode(...new Uint8Array(res.data)))}`);
return `data:${res.headers['content-type']};base64,${btoa(String.fromCharCode(...new Uint8Array(res.data)))}`;
})
.catch((e) => {
console.log(e);
});
}
const imgFond = await getImage('fond.jpeg');
const imgEtoile = await getImage('etoile.png');
function initCarte() {
console.log('init de la carte');
// changer les chargement
// https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations
requestAnimationFrame(initCarte);
now = Date.now();
elapsed = now - then;
if (elapsed > fpsInterval) {
then = now - (elapsed % fpsInterval);
petit.value = window.innerWidth < 750;
const etoile = new Image();
// etoile.src = `${process.env.VUE_APP_PUBLICPATH}img/etoile.png`;
etoile.src = imgEtoile;
const background = new Image();
// background.src = `${process.env.VUE_APP_PUBLICPATH}img/fond.jpeg`;
background.src = imgFond;
background.onload = () => {
rapport.value = background.naturalWidth / background.naturalHeight;
tailleFond.w = background.naturalWidth;
tailleFond.h = background.naturalHeight;
size.w = window.innerWidth * taille.value;
size.h = size.w / rapport.value;
if (size.w > window.innerWidth) {
size.h = size.w / rapport.value;
} else if (size.h > window.innerHeight) {
size.h = window.innerHeight * taille.value;
size.w = size.h * rapport.value;
}
nextTick(() => {
try {
myCanvas.value.drawImage(background, 0, 0, size.w, size.h);
// on dessine les étoiles
etoiles.value.forEach((e) => {
if (e.grossissement.valeur > 2 && e.grossissement.sens === 1) {
e.grossissement.sens = -1;
}
if (e.grossissement.valeur < -3 && e.grossissement.sens === -1) {
e.grossissement.sens = 1;
}
if (e.deviation.x.valeur > e.deviation.x.amplitude && e.deviation.x.sens === 1) {
e.deviation.x.sens = -1;
}
if (e.deviation.x.valeur < -e.deviation.x.amplitude && e.deviation.x.sens === -1) {
e.deviation.x.sens = 1;
}
if (e.deviation.y.valeur > e.deviation.y.amplitude && e.deviation.y.sens === 1) {
e.deviation.y.sens = -1;
}
if (e.deviation.y.valeur < -e.deviation.y.amplitude && e.deviation.y.sens === -1) {
e.deviation.y.sens = 1;
}
e.deviation.x.valeur += e.deviation.x.sens;
e.deviation.y.valeur += e.deviation.y.sens;
e.grossissement.valeur += e.grossissement.sens;
myCanvas.value.drawImage(etoile,
(e.position.x * size.w) + e.deviation.x.valeur - e.grossissement.valeur / 2,
(e.position.y * size.h) + e.deviation.y.valeur - e.grossissement.valeur / 2,
(e.taille + e.grossissement.valeur) * (size.w / background.naturalWidth),
(e.taille + e.grossissement.valeur) * (size.h / background.naturalHeight));
});
// on dessine 2021
const fontSize = 0.1 * size.w - 10;
myCanvas.value.font = `${fontSize}px Caviar Dream`;
myCanvas.value.textAlign = 'center';
myCanvas.value.fillStyle = 'white';
myCanvas.value.strokeStyle = 'black';
myCanvas.value.lineWidth = 0.006 * size.w - 10;
const x = (size.w * 7) / 12;
const y = (size.h * 4) / 9;
const ecart = 0.07 * size.w - 10;
date.value.forEach((ch, i) => {
if (ch.valeur.position > 6 && ch.valeur.sens === 1) {
ch.valeur.sens = -1;
}
if (ch.valeur.position < -6 && ch.valeur.sens === -1) {
ch.valeur.sens = 1;
}
ch.valeur.position += 1 * ch.valeur.sens;
myCanvas.value.fillText(
ch.valeur.chiffre,
x + (ecart * i),
y + ch.valeur.position,
);
});
} catch (e) {
console.log(`ERREUR DE CHARGEMENT D'IMAGE: ${e}`);
}
if (!petit.value) {
drawText();
}
});
};
}
}
function startAnimating(fps) {
fpsInterval = 1000 / fps;
then = Date.now();
startTime = then;
console.log(startTime);
initCarte();
}
window.addEventListener('resize', initCarte);
return {
myCanvas,
size,
texte,
petit,
carte,
tailleFond,
};
},
});
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#font-face {
font-family: 'Caviar Dream';
src: local('Caviar Dream'), url(~#/assets/fonts/CaviarDreams.ttf) format('truetype');
}
#texteRemplacement {
font-size: 20pt;
font-family: 'Caviar Dream';
}
#myCanvas {
border: 1px solid grey;
}
</style>
What did I not understand in this page?

TypeError: Cannot read property 'width' of undefined - Nuxt JS and canvas

I am trying to run a sketch on the canvas element in Nuxt JS but I am having some issues (I am completely new to Vue JS).
While I have no errors in VS Code, there is an error in the browser console:
client.js?06a0:84 TypeError: Cannot read property 'width' of undefined
at Blob.get (Blob_Point.js?a5e5:126)
at Blob.render (Blob_Point.js?a5e5:29)
below is the code for my Vue file:
<template>
<div>
<h1 class="pa-5 text-center">Blob</h1>
<canvas id="myCanvas" width="600" height="400"></canvas>
<!--<v-btn #click="drawRect">Clear</v-btn> -->
</div>
</template>
<script>
import Blob from "../assets/content/Blob_Point"
//import { Point } from "../assets/content/Blob_Point"
//import Point from "../assets/content/Blob_Point"
let oldMousePoint = { x: 0, y: 0 }
let blob = new Blob()
//let point = new Point()
let hover = false
let canvas
export default {
data() {
return {
canvas: null,
x: 0,
y: 0,
isDrawing: false,
rectWidth: 200,
//hover: false,
//oldMousePoint: { x: 0, y: 0 },
}
},
mounted() {
let canvas = document.getElementById("myCanvas")
this.canvas = canvas.getContext("2d")
},
created() {
new Blob("#C09EFF")
blob.canvas = canvas
blob.init()
blob.render()
},
methods: {
/* showCoordinates(e) {
this.x = e.offsetX
this.y = e.offsetY
},
drawLine(x1, y1, x2, y2) {
let ctx = this.vueCanvas
ctx.beginPath()
ctx.strokeStyle = "black"
ctx.lineWidth = 1
ctx.moveTo(x1, y1)
ctx.lineTo(x2, y2)
ctx.stroke()
ctx.closePath()
},
draw(e) {
if (this.isDrawing) {
this.drawLine(this.x, this.y, e.offsetX, e.offsetY)
this.x = e.offsetX
this.y = e.offsetY
}
},
beginDrawing(e) {
this.x = e.offsetX
this.y = e.offsetY
this.isDrawing = true
},
stopDrawing(e) {
if (this.isDrawing) {
this.drawLine(this.x, this.y, e.offsetX, e.offsetY)
this.x = 0
this.y = 0
this.isDrawing = false
//windowWidth = 0,
}
}, */
resize() {
document.getElementById("myCanvas").width = window.innerWidth
document.getElementById("myCanvas").height = window.innerHeight
},
/*drawRect() {
this.vueCanvas.clearRect(0, 0, 600, 800)
//this.vueCanvas.beginPath()
//this.vueCanvas.rect(20, 20, this.rectWidth, 100)
//this.vueCanvas.stroke()
},*/
mouseMove(e) {
let pos = blob.center
let diff = { x: e.clientX - pos.x, y: e.clientY - pos.y }
let dist = Math.sqrt(diff.x * diff.x + diff.y * diff.y)
let angle = null
blob.mousePos = {
x: pos.x - e.clientX,
y: pos.y - e.clientY,
}
if (dist < blob.radius && hover === false) {
let vector = {
x: e.clientX - pos.x,
y: e.clientY - pos.y,
}
angle = Math.atan2(vector.y, vector.x)
hover = true
// blob.color = '#77FF00';
} else if (dist > blob.radius && hover === true) {
let vector = {
x: e.clientX - pos.x,
y: e.clientY - pos.y,
}
angle = Math.atan2(vector.y, vector.x)
hover = false
blob.color = null
}
if (typeof angle == "number") {
let nearestPoint = null
let distanceFromPoint = 100
blob.points.forEach((point) => {
if (Math.abs(angle - point.azimuth) < distanceFromPoint) {
// console.log(point.azimuth, angle, distanceFromPoint);
nearestPoint = point
distanceFromPoint = Math.abs(angle - point.azimuth)
}
})
if (nearestPoint) {
let strength = {
x: oldMousePoint.x - e.clientX,
y: oldMousePoint.y - e.clientY,
}
strength =
Math.sqrt(strength.x * strength.x + strength.y * strength.y) * 1
if (strength > 100) strength = 100
nearestPoint.acceleration = (strength / 100) * (hover ? -1 : 1)
}
}
oldMousePoint.x = e.clientX
oldMousePoint.y = e.clientY
},
},
}
</script>
<style scoped>
#myCanvas {
border: 1px solid grey;
}
</style>
and below is the Blob_Point JS file that I am importing:
/* eslint-disable */
// Blob Class
export default class Blob {
// setup function
constructor(color) {
//the objects setup
// 'this' is a reference to the current class
this.points = []
this._color = color
}
init() {
for (let i = 0; i < this.numPoints; i++) {
let point = new Point(this.divisional * (i + 1), this)
//point.acceleration = -1 + Math.random() * 2;
this.push(point)
}
}
render() {
let canvas = this.canvas
let ctx = this.ctx
let position = this.position
let pointsArray = this.points
let radius = this.radius
let points = this.numPoints
let divisional = this.divisional
let center = this.center
ctx.clearRect(0, 0, canvas.width, canvas.height)
pointsArray[0].solveWith(pointsArray[points - 1], pointsArray[1])
let p0 = pointsArray[points - 1].position
let p1 = pointsArray[0].position
let _p2 = p1
// this is the draw
ctx.beginPath()
ctx.moveTo(center.x, center.y)
ctx.moveTo((p0.x + p1.x) / 2, (p0.y + p1.y) / 2)
for (let i = 1; i < points; i++) {
pointsArray[i].solveWith(
pointsArray[i - 1],
pointsArray[i + 1] || pointsArray[0]
)
let p2 = pointsArray[i].position
var xc = (p1.x + p2.x) / 2
var yc = (p1.y + p2.y) / 2
ctx.quadraticCurveTo(p1.x, p1.y, xc, yc)
// ctx.lineTo(p2.x, p2.y);
//ctx.fillStyle = this.color;
// ctx.fillRect(p1.x-2.5, p1.y-2.5, 5, 5);
p1 = p2
}
var xc = (p1.x + _p2.x) / 2
var yc = (p1.y + _p2.y) / 2
ctx.quadraticCurveTo(p1.x, p1.y, xc, yc)
ctx.lineTo(_p2.x, _p2.y)
ctx.closePath()
ctx.fillStyle = this.color
ctx.fill()
ctx.strokeStyle = this.color
// ctx.stroke();
/*
ctx.fillStyle = '#000000';
if(this.mousePos) {
let angle = Math.atan2(this.mousePos.y, this.mousePos.x) + Math.PI;
}*/
//requestAnimationFrame(this.render.bind(this))
}
push(item) {
if (item instanceof Point) {
this.points.push(item)
}
}
set color(value) {
this._color = value
}
get color() {
return this._color
}
set canvas(value) {
if (
value instanceof HTMLElement &&
value.tagName.toLowerCase() === "canvas"
) {
this._canvas = canvas
this.ctx = this._canvas.getContext("2d")
}
}
get canvas() {
return this._canvas
}
set numPoints(value) {
if (value > 10) {
this._points = value
}
}
get numPoints() {
return this._points || 32
}
set radius(value) {
if (value > 0) {
this._radius = value
}
}
get radius() {
return this._radius || 300
}
set position(value) {
if (typeof value == "object" && value.x && value.y) {
this._position = value
}
}
get position() {
return this._position || { x: 0.5, y: 0.5 }
}
get divisional() {
return (Math.PI * 2) / this.numPoints
}
get center() {
return {
x: this.canvas.width * this.position.x,
y: this.canvas.height * this.position.y,
}
}
set running(value) {
this._running = value === true
}
get running() {
return this.running !== false
}
}
// Point Class
export class Point {
constructor(azimuth, parent) {
this.parent = parent
this.azimuth = Math.PI - azimuth
this._components = {
x: Math.cos(this.azimuth),
y: Math.sin(this.azimuth),
}
this.acceleration = -0.3 + Math.random() * 0.6
}
solveWith(leftPoint, rightPoint) {
this.acceleration =
(-0.3 * this.radialEffect +
(leftPoint.radialEffect - this.radialEffect) +
(rightPoint.radialEffect - this.radialEffect)) *
this.elasticity -
this.speed * this.friction
}
set acceleration(value) {
if (typeof value == "number") {
this._acceleration = value
this.speed += this._acceleration * 2
}
}
get acceleration() {
return this._acceleration || 0
}
set speed(value) {
if (typeof value == "number") {
this._speed = value
this.radialEffect += this._speed * 3
}
}
get speed() {
return this._speed || 0
}
set radialEffect(value) {
if (typeof value == "number") {
this._radialEffect = value
}
}
get radialEffect() {
return this._radialEffect || 0
}
get position() {
return {
x:
this.parent.center.x +
this.components.x * (this.parent.radius + this.radialEffect),
y:
this.parent.center.y +
this.components.y * (this.parent.radius + this.radialEffect),
}
}
get components() {
return this._components
}
set elasticity(value) {
if (typeof value === "number") {
this._elasticity = value
}
}
get elasticity() {
return this._elasticity || 0.001
}
set friction(value) {
if (typeof value === "number") {
this._friction = value
}
}
get friction() {
return this._friction || 0.0085
}
}
Any ideas on the why lines 29 and 127 of the Blob_Point.js file are throwing errors?
I attached 2 screens of the developer tools in chrome to show the errors along with the JS its pointing to.
Thanks for any help!
The main issue I can identify is here. I have added comments to the code.
Blob_Point.js
render() {
let canvas = this.canvas // this references the Blob Class (not the Vue instance) and there is no initialised property such as canvas in the class
}
To fix this main issue, you can do something like
Blob_Point.js
export default class Blob {
constructor(color, canvas) {
//the objects setup
// 'this' is a reference to the current class
this.points = []
this._color = color;
this.canvas = canvas
}
}
And then in the .vue file
.Vue
mounted() {
let canvas = document.getElementById("myCanvas");
this.canvas = canvas.getContext("2d");
blob = new Blob("#C09EFF", this.canvas); // now canvas in the Blob Class constructor will refer to the vue instance canvas
blob.canvas = canvas;
blob.init();
blob.render();
},
I have identified another issue here.
set canvas(value) {
if (
value instanceof HTMLElement &&
value.tagName.toLowerCase() === "canvas"
) {
this._canvas = canvas // there is no initialised constructor property as _canvas
this.ctx = this._canvas.getContext("2d") // there is no initialised constructor property such as _canvas
}
}
get canvas() {
return this._canvas // there is no initialised constructor property as _canvas
}

OrbitControls are not working react-native

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;
```

KineticJs-how to update x and y position of the multiple images after resizing the stage layer

As I am new to KineticJs so, I have tried implementing the functionality using Kinectic js for drawing the multiple image on different- different x and y. Now I wanted to resize the stage layer or canvas. I have done that by using the code given below
window.onresize = function (event) {
stage.setWidth(($('#tab' + tabId).innerWidth() / 100) * 80);
var _images = layer.getChildren();
for (var i = 0; i < _images.length; i++) {
if (typeof _images[i].getId() != 'undefined') {
//alert(stage.getScale().x);
_images[i].setX(_images[i].getX() * stage.getScale().x);
layer.draw();
}
}
}
but now the problem is the are being defined and now if browser resize than stage is resized but the images on the prev x and y are fixed . I would like to keep them fixed on the position on resizing of stage layer or canvas.Here are the link of the image before resize and after resizing.beforeresize and afterResize .
Here is my entire code given below:-
$("#tabs li").each(function () {
$(this).live("click", function () {
clearInterval(_timer);
var tabname = $(this).find("a").attr('name');
tabname = $.trim(tabname.replace("#tab", ""));
var tabId = $(this).find("a").attr('href');
tabId = $.trim(tabId.replace("#", ""));
$.ajax({
url: "/Home/GetTabsDetail",
dataType: 'json',
type: 'GET',
data: { tabId: tabId },
cache: false,
success: function (data) {
var bayStatus = [];
var i = 0;
var image_array = [];
var BayExist = false;
var BayCondition;
var imgSrc;
var CanvasBacgroundImage;
var _X;
var _bayNumber;
var _Y;
var _ZoneName;
$(data).each(function (i, val) {
i = i + 1;
if (!BayExist) {
bayStatus = val.BayStatus;
CanvasBacgroundImage = val.TabImageLocation;
BayExist = true;
}
$.each(val, function (k, v) {
if (k == "BayNumber") {
BayCondition = bayStatus[v];
_bayNumber = v;
if (BayCondition == "O")
imgSrc = "../../images/Parking/OccupiedCar.gif"
else if (BayCondition == "N")
imgSrc = "../../images/Parking/OpenCar.gif";
}
if (k == "BayX")
_X = v;
if (k == "BayY")
_Y = v;
if (k == "ZoneName")
_ZoneName = v;
});
image_array.push({ img: imgSrc, xAxis: _X, yAxis: _Y, toolTip: _bayNumber, ZoneName: _ZoneName });
});
var imageUrl = CanvasBacgroundImage;
if ($('#tab' + tabId).length) {
// $('#tab' + tabId).css('background-image', 'url("../../images/Parking/' + imageUrl + '")');
var stage = new Kinetic.Stage({
container: 'tab' + tabId,
width: ($('#tab' + tabId).innerWidth() / 100) * 80, // 80% width of the window.
height: 308
});
window.onresize = function (event) {
stage.setWidth(($('#tab' + tabId).innerWidth() / 100) * 80);
}
$('#tab' + tabId).find('.kineticjs-content').css({ 'background-image': 'url("../../images/Parking/' + imageUrl + '")', 'background-repeat': ' no-repeat', 'background-size': '100% 100%' });
var layer = new Kinetic.Layer();
var planetOverlay;
function writeMessage(message, _x, _y) {
text.setX(_x + 20);
text.setY(_y + 1);
text.setText(message);
layer.draw();
}
var text = new Kinetic.Text({
fontFamily: 'Arial',
fontSize: 14,
text: '',
fill: '#000',
width: 200,
height: 60,
align: 'center'
});
var opentooltip = new Opentip(
"div#tab" + tabId, //target element
"dummy", // will be replaced
"", // title
{
showOn: null // I'll manually manage the showOn effect
});
Opentip.styles.win = {
borderColor: "black",
shadow: false,
background: "#EAEAEA"
};
Opentip.defaultStyle = "win";
// _timer = setInterval(function () {
for (i = 0; i < image_array.length; i++) {
img = new Image();
img.src = image_array[i].img;
planetOverlay = new Kinetic.Image({
x: image_array[i].xAxis,
y: image_array[i].yAxis,
image: img,
height: 18,
width: 18,
id: image_array[i].toolTip,
name: image_array[i].ZoneName
});
planetOverlay.on('mouseover', function () {
opentooltip.setContent("<span style='color:#87898C;'><b>Bay:</b></span> <span style='color:#25A0D3;'>" + this.getId() + "</span><br> <span style='color:#87898C;'><b>Zone:</b></span><span style='color:#25A0D3;'>" + this.getName() + "</span>");
//writeMessage("Bay: " + this.getId() + " , Zone: " + this.getName(), this.getX(), this.getY());//other way of showing tooltip
opentooltip.show();
$("#opentip-1").offset({ left: this.getX(), top: this.getY() });
});
planetOverlay.on('mouseout', function () {
opentooltip.hide();
// writeMessage('');
});
planetOverlay.createImageHitRegion(function () {
layer.draw();
});
layer.add(planetOverlay);
layer.add(text);
stage.add(layer);
}
// clearInterval(_timer);
//$("#tab3 .kineticjs-content").find("canvas").css('background-image', 'url("' + imageUrl + '")');
// },
// 500)
}
}
,
error: function (result) {
alert('error');
}
});
});
});
I want to keep the icons on the position where they were before resizing. I have tried but could not get the right solution to get this done.
How can How can I update x,y position for the images . Any suggestions would be appreciated.
Thanks is advance.
In window.resize, you're changing the stage width by a scaling factor.
Save that scaling factor.
Then multiply the 'x' coordinate of your images by that scaling factor.
You can reset the 'x' position of your image like this:
yourImage.setX( yourImage.getX() * scalingFactor );
layer.draw();
In the above mentioned code for window.onresize. The code has been modified which as follow:-
window.onresize = function (event) {
_orignalWidth = stage.getWidth();
var _orignalHeight = stage.getHeight();
// alert(_orignalWidth);
// alert($('#tab' + tabId).outerHeight());
stage.setWidth(($('#tab' + tabId).innerWidth() / 100) * 80);
//stage.setHeight(($('#tab' + tabId).outerHeight() / 100) * 80);
_resizedWidth = stage.getWidth();
_resizedHeight = stage.getHeight();
// alert(_resizedWidth);
_scaleFactorX = _resizedWidth / _orignalWidth;
var _scaleFactorY = _resizedHeight / _orignalHeight;
//alert(_scaleFactor);
var _images = layer.getChildren();
for (var i = 0; i < _images.length; i++) {
if (typeof _images[i].getId() != 'undefined') {
//alert(stage.getScale().x);
_images[i].setX(_images[i].getX() * _scaleFactorX);
//_images[i].setY(_images[i].getY() * _scaleFactorY);
layer.draw();
}
}
}