React hooks - Update State in function - reactjs

hi i have an issue with set state , i write the function that i get Position x,y and size of width , height(That is the name of the state that holds them POx1, POY1, widthSize, heightSize) and depend on user choise, i change the state's that user get to me and Use them. but after the first setSate for all these State i can't update and or change them . these are my code's:
function DrawPicture() { // this function call after click
setCountClick(CountClick + 1);
var Se_image = new Image();
Se_image.src = ImgSRC;// (ImgSRC) is the State i define it before
Se_image.onload = function () {
ctxRef.current.globalCompositeOperation = "source-over";
if (CountClick === 2) {// For some reason, I want this condition to be executed after calling the above function twice
var img = Se_image
PictureCategory(img) // This function is shown below
var canvas = canvasRef.current
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(POx1, POY1, widthSize, heightSize);
var data = imageData.data;
console.log(lineColor);
const r = parseInt(lineColor.substr(1, 2), 16)
const g = parseInt(lineColor.substr(3, 2), 16)
const b = parseInt(lineColor.substr(5, 2), 16)
var changeColor = function () {
for (var i = 0; i < data.length; i += 4) {
data[i] = r
data[i + 1] = g
data[i + 2] = b
}
ctx.putImageData(imageData, POx1, POY1);
};
changeColor();
setCountClick(1);
setPointer(false);
}
}
}
and this is my PictureCategory() function:
For convenience, I only took one of the modes
function PictureCategory(image) {
switch (PictureTopic) {
case "Girl":
const XG = POx1 - (0.5 * widthSize) < 0 ? 0 : POx1 - (0.5 * widthSize);
const newWidth= 2.4*widthSize;
const newheight= 2.5*widthSize;
setPOx1(XG)
setwidthSize(newWidth)
setheightSize(newheight)
ctxRef.current.clearRect(XG, POY1, newWidth, newheight);
ctxRef.current.drawImage(image, XG, POY1, 2.4 * widthSize, 2.5 * heightSize);
break;
default:
ctxRef.current.drawImage(image, POx1, POY1, widthSize, heightSize);
break;
}
}
i want to change state's with above function please help me !!!

Not sure if it'll fix your issue, but the following has to be done in any case.
It should be
setCountClick(countClick=> countClick + 1);
When state is updated using its previous value, the callback argument of the state setter should be used.
See https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

i know it's not your answer for this question. but you can use this codes for have new value .
I stored the new values in an object and returned them:
function DrawPicture() {
setCountClick(CountClick + 1);
var Se_image = new Image();
Se_image.src = ImgSRC;
Se_image.onload = function () {
ctxRef.current.globalCompositeOperation = "source-over";
if (CountClick === 2) {
var img = Se_image
const Sizes =PictureCategory(img) // you can store new value in valible
var canvas = canvasRef.current
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(Sizes[0].x, Sizes[0].y, Sizes[0].width, Sizes[0].height);
var data = imageData.data;
console.log(lineColor);
const r = parseInt(lineColor.substr(1, 2), 16)
const g = parseInt(lineColor.substr(3, 2), 16)
const b = parseInt(lineColor.substr(5, 2), 16)
var changeColor = function () {
for (var i = 0; i < data.length; i += 4) {
data[i] = r
data[i + 1] = g
data[i + 2] = b
}
ctx.putImageData(imageData,Sizes[0].x, Sizes[0].y);
};
changeColor();
setCountClick(1);
setPointer(false);
}
}
}
function PictureCategory(image) {
switch (PictureTopic) {
case "Girl":
const XG = POx1 - (0.5 * widthSize) < 0 ? 0 : POx1 - (0.5 * widthSize);
const newWidth= 2.4*widthSize;
const newheight= 2.5*widthSize;
ctxRef.current.clearRect(XG, POY1, newWidth, newheight);
ctxRef.current.drawImage(image, XG, POY1, 2.4 * widthSize, 2.5 * heightSize);
return[{x: XG,y:POY1,width:newWidth,height:newheight}]
default:
ctxRef.current.drawImage(image, POx1, POY1, widthSize, heightSize);
break;
}
}

Related

How do you create an array of meshes in scene in THREE.JS?

I'm trying to create an array of meshes I added to my THREE.JS scene because I used a for-loop with the load() function to create the instances of the meshes, and I wanted to reference them later for the animate() function. The array shows a list of values in the console, but the length shows up as 0 when logged. This is the code I have:
const manager = new THREE.LoadingManager(); //loading manager
const loader = new GLTFLoader(manager);
let pos_arr = []
manager.onLoad = function(e) {
scene.traverse( function (model) {
if (model.isMesh) {
pos_arr.push(model)
}
})
}
let pos = new THREE.Vector3()
//spheres and equators
let ball = new THREE.Mesh();
let equator = new THREE.Mesh()
for (let i = 1; i <= 12; i++) {
let scale = Math.floor(Math.random() * 3) + 1
let pos_x = Math.floor(Math.random() * 10) * 5 - 25
let pos_y = Math.floor(Math.random() * 10) * 5 - 25
let pos_z = Math.floor(Math.random() * 10) * 5 - 25
pos = new THREE.Vector3(pos_x, pos_y, pos_z)
loader.load( './ball.gltf', function ( gltf ) { //load sphere
gltf.scene.traverse(function(model) {
if (model.isMesh) {
model.castShadow = true;
model.material = sphereMaterial;
}
});
ball = gltf.scene
ball.position.set(pos_x, pos_y, pos_z)
ball.scale.set(scale, scale, scale)
scene.add( ball );
}, undefined, function ( error ) {
console.error( error );
} );
loader.load( './equator.gltf', function ( gltf2 ) {
gltf2.scene.traverse(function(model) { //for gltf shadows!
if (model.isMesh) {
model.castShadow = true
model.material = equatorMaterial
}
});
equator = gltf2.scene
equator.position.set(pos_x, pos_y, pos_z)
equator.scale.set(scale, scale, scale)
scene.add( equator )
}, undefined, function ( error ) {
console.error( error )
} );
}
//light
const light = new THREE.AmbientLight( 0xffffff );
scene.add( light );
console.log(pos_arr)
console.log(pos_arr.length)
This is what the console shows:
I got a recommendation that I use the onLoad attribute for the LoadingManager, which I used, but it didn't work. If anyone happens to know a possible solution, it would be greatly appreciated :)

Creating a javascript array to localstorage not returning desired result

I'm trying to create an array to localstorage containing some gear box values, witch I then need again to do some more calculations with specific array[?].value.
The problem I'm encountering is that the created entry returns only 2 array entries, although all entries are there but the " is at the beginning and then at the second last entry and then before and after the last entry.
These are the values generated.
spd_Dev = ["202.391,172.876,120.451,102.601,85.173,72.664,61.701,52.706,45.116,38.510,32.326,27.407,22.910,19.536,16.585,14.195,12.228","10.401"]
When I used to use a fixed array I've entered it as:
var spd_Dev = [202.391, 172.876, 120.451, 102.601, 85.173, 72.664, 61.701, 52.706, 45.116, 38.510, 32.326, 27.407, 22.910, 19.536, 16.585, 14.195, 12.228, 10.401];
So my question is how to write this values to localstorage and read again from localstorage so that I can use this values as an array.
This is what I'm trying to work.
var D_RatioId = data.truck.make + data.truck.model + "D_Ratio"
var G_RatioId = data.truck.make + data.truck.model + "G_Ratio"
var fGr = data.truck.forwardGears;
var gr = data.truck.displayedGear;
var Rpm = data.truck.engineRpm * 100;
var spd = data.truck.speed;
var T_Dia = 1008.3;
if (localStorage.getItem(G_RatioID) == undefined) {
localStorage.setItem(G_RatioID, '');
var fG_Rat = [localStorage.getItem(G_RatioID)];
} else {
var fG_Rat = [localStorage.getItem(G_RatioID)];
}
var spd_Dev = localStorage.getItem(Spd_DevId);
spd_Dev = spd_Dev ? spd_Dev.split(', ') : [];
if (localStorage.getItem("i") == undefined) {
localStorage.setItem("i", 1);
var i = localStorage.getItem("i");
} else {
var i = localStorage.getItem("i");
}
if (i <= fGr && spd > 0.5) {
if (i <= fGr + 1) {
if (i == gr) {
if (RPM > 1450) {
var G_Ratio = Math.abs(Rpm / D_Ratio * (Math.PI * T_Dia / 1000) * 60 / spd / 1000, 2).toFixed(2);
var spd_D = Math.abs(RPM / (RPM / G_Ratio / D_Ratio * (Math.PI * T_Dia / 1000) * 60 / 1000) * 0.821932).toFixed(3);
fG_Rat.push(G_Ratio);
spd_Dev.push(spd_D);
i++;
localStorage.setItem("i", i);
var G_RatioValue = fG_Rat;
var Spd_DevValue = spd_Dev;
SetG_Ratio(G_RatioID, G_RatioValue);
SetSpd_Dev(Spd_DevId, Spd_DevValue);
localStorage.setItem("spd_Dev", JSON.stringify(Spd_DevValue));
}
}
}
}
function SetG_Ratio(G_RatioID, G_RatioValue) {
localStorage.setItem(G_RatioID, G_RatioValue);
console.log(G_RatioID, G_RatioValue);
}
function SetSpd_Dev(Spd_DevId, Spd_DevValue) {
localStorage.setItem(Spd_DevId, Spd_DevValue.toString());
console.log(Spd_DevId, Spd_DevValue, Spd_DevValue.length);
}
if (spd >= 0) {
var spd_Dev = [localStorage.getItem(Spd_DevId)];
var spD_D = JSON.parse(spd_Dev);
for (i = 1; i < (fGr + 1); i++) { // Some more code dependant on the above results //
why don't you use LSM.js? it will make everything simpler. you can put the array as an array so that it will return the full array only, you will not need to use split(),
https://github.com/kevinj045/LSM_js
var lsm = new LSM("G_RatioID");
var G_RatioValue ["202.391,172.876,120.451,102.601,85.173,72.664,61.701,52.706,45.116,38.510,32.326,27.407,22.910,19.536,16.585,14.195,12.228","10.401"];
lsm.set("G_RatioID",G_RatioValue);
console.log(lsm.get("G_RatioID")); // it will return the full array

Question About Order of Execution of Functions in React

In the following code, why is the sleep function executed before the startClock function?
handleClick = () => {
this.startClock();
this.sleep(5000);
}
startClock = () => {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
// add a zero in front of numbers<10
m = this.checkTime(m);
s = this.checkTime(s);
document.getElementById("txt").innerHTML = h + ":" + m + ":" + s;
console.log(h + ":" + m + ":" + s);
var t = setTimeout(function(){this.startClock()}.bind(this), 1000);
};
checkTime = (i) => {
if (i < 10) {
i = "0" + i;
}
return i;
};
sleep = (timeout) => {
var begin = new Date();
while (new Date() - begin < timeout) {
}
};
I would expect the startClock function to execute first but the sleep function executes first and then the startClock function.
I think what is actually happening here is the startClock function is executed first but since the time specified in setTimeout is 1000ms, the sleep function starts before the GUI is updated and therefore the GUI is not updated until sleep is finished.

Mixpanel Data to Google Sheets

I am trying to push mixpanel data into a single Google Sheet using code from here:
https://github.com/melissaguyre/mixpanel-segmentation-google-spreadsheets
I am having issues with the API_PARAMETERS not looping through as expected. (Formula, Formula1, & Formula2) The first two parameters loop through fine, but when the final is added, I get the error:
TypeError: Cannot read property "2016-07-11" from undefined. (line 143, file "Code")
Here is the code:
* Step 1) Fill in your account's Mixpanel Information here
`enter code here`*/
var API_KEY = '******';
var API_SECRET = '****';
/**
* Step 2) Define the tab # at which to create new sheets in the spreadsheet.
* 0 creates a new sheet as the first sheet.
* 1 creates a new sheet at the second sheet and so forth.
*/
var CREATE_NEW_SHEETS_AT = 0;
/**
* Step 3) Define date range as a string in format of 'yyyy-mm-dd' or '2013-09-13'
*
* Today's Date: set equal to getMixpanelDateToday()
* Yesterday's Date: set equal to getMixpanelDateYesterday()
*/
var FROM_DATE = getMixpanelDate(7);
var TO_DATE = getMixpanelDate(1);
/**
* Step 4) Define Segmentation Queries - Get data for an event, segmented and filtered by properties.
var API_PARAMETERS = {
'Formula' : [ 'QuestionAsked', '(properties["InputMethod"]) == "Voice" or (properties["InputMethod"]) == "Text" ', 'general', 'day', 'B7'],
'Formula1' : [ 'QuestionAsked', '(properties["InputMethod"]) == "Voice" or (properties["InputMethod"]) == "Text" ', 'unique', 'day', 'B2'],
//'Formula2' : [ 'QuestionAnswered', '(properties["InputMethod"]) == "Voice" or (properties["InputMethod"]) == "Text" ', 'unique', 'day', 'B3' ],
};
// Iterates through the hash map of queries, gets the data, writes it to spreadsheet
function getMixpanelData() {
for (var i in API_PARAMETERS)
{
var cell = API_PARAMETERS[i][4];
fetchMixpanelData(i, cell);
}
}
// Creates a menu in spreadsheet for easy user access to above function
function onOpen() {
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
activeSpreadsheet.addMenu(
"Mixpanel", [{
name: "Get Mixpanel Data", functionName: "getMixpanelData"
}]);
}
/**
* Gets data from mixpanel api and inserts to spreadsheet
*
*/
function fetchMixpanelData(sheetName, cell) {
var c = cell;
var expires = getApiExpirationTime();
var urlParams = getApiParameters(expires, sheetName).join('&')
+ "&sig=" + getApiSignature(expires, sheetName);
// Add URL Encoding for special characters which might generate 'Invalid argument' errors.
// Modulus should always be encoded first due to the % sign.
urlParams = urlParams.replace(/\%/g, '%25');
urlParams = urlParams.replace(/\s/g, '%20');
urlParams = urlParams.replace(/\[/g, '%5B');
urlParams = urlParams.replace(/\]/g, '%5D');
urlParams = urlParams.replace(/\"/g, '%22');
urlParams = urlParams.replace(/\(/g, '%28');
urlParams = urlParams.replace(/\)/g, '%29');
urlParams = urlParams.replace(/\>/g, '%3E');
urlParams = urlParams.replace(/\</g, '%3C');
urlParams = urlParams.replace(/\-/g, '%2D');
urlParams = urlParams.replace(/\+/g, '%2B');
urlParams = urlParams.replace(/\//g, '%2F');
var url = "http://mixpanel.com/api/2.0/segmentation?" + urlParams;
Logger.log("THE URL " + url);
var response = UrlFetchApp.fetch(url);
var json = response.getContentText();
var dataAll = JSON.parse(json);
var dates = dataAll.data.series;
Logger.log(API_PARAMETERS);
for (i in API_PARAMETERS){
var parametersEntry = API_PARAMETERS[i];
for (i in dates){
data = dataAll.data.values[parametersEntry[0]][dates[i]];
}
insertSheet(data, c);
};
}
function insertSheet(value, cell) {
var sheetName = 'Formula';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sheetName);
var c = sheet.getRange(cell).setValue(value);
};
/**
* Returns an array of query parameters
*/
function getApiParameters(expires, sheetName) {
var parametersEntry = API_PARAMETERS[sheetName];
return [
'api_key=' + API_KEY,
'expire=' + expires,
'event=' + parametersEntry[0],
'where=' + parametersEntry[1],
'type=' + parametersEntry[2],
'unit=' + parametersEntry[3],
'from_date=' + FROM_DATE,
'to_date=' + TO_DATE
];
}
/**
* Sorts provided array of parameters
*
function sortApiParameters(parameters) {
var sortedParameters = parameters.sort();
// Logger.log("sortApiParameters() " + sortedParameters);
return sortedParameters;
}
/**
function getApiExpirationTime() {
var expiration = Date.now() + 10 * 60 * 1000;
// Logger.log("getApiExpirationTime() " + expiration);
return expiration;
}
/**
* Returns API Signature calculated using api_secret.
*/
function getApiSignature(expires, sheetName) {
var parameters = getApiParameters(expires, sheetName);
var sortedParameters = sortApiParameters(parameters).join('') + API_SECRET;
// Logger.log("Sorted Parameters " + sortedParameters);
var digest = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, sortedParameters);
var signature = '';
for (j = 0; j < digest.length; j++) {
var hashVal = digest[j];
if (hashVal < 0) hashVal += 256;
if (hashVal.toString(16).length == 1) signature += "0";
signature += hashVal.toString(16);
}
return signature;
}
/**
*********************************************************************************
* Date helpers
*********************************************************************************
*/
// Returns today's date string in Mixpanel date format '2013-09-11'
function getMixpanelDateToday() {
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
var yyyy = today.getFullYear();
if (dd < 10) {
dd = '0' + dd;
}
if ( mm < 10 ) {
mm = '0' + mm;
}
today = yyyy + '-' + mm + '-' + dd;
return today;
}
// Returns yesterday's's date string in Mixpanel date format '2013-09-11'
function getMixpanelDate(days){
var today = new Date();
var d = new Date(today);
d.setDate(today.getDate() - days);
//Logger.log(yesterday);
var dd = d.getDate();
//Logger.log(yesterday);
var mm = d.getMonth() + 1;
var yyyy = d.getFullYear();
if (dd < 10) {
dd = '0' + dd;
}
if (mm < 10) {
mm = '0' + mm;
}
d = yyyy + '-' + mm + '-' + dd;
//Logger.log(yesterday);
return d;
}

set array to hold images verses text, flash actionscript

the following flash actionscript below stores letters and numbers into an array and displays them randomly in a flash movie as "falling text" down the screen. I'd like to modify this script so I can have the array store multiple images verses letters and numbers.
source:
http://www.flashcomponents.net/tutorials/letter_and_number_rain_flash_tutorial/page_1.html
--- layer script
var letter_array = new Array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","1","2","3","4","5","6","7","8","9","0");
var i = 0;
setInterval(nLetter, 70);
function nLetter()
{
duplicateMovieClip(letterMC, "letter" + i, 10 + i);
i++
}
-------- symbol script
onClipEvent(load)
{
var index = Math.round(Math.random() * _root.letter_array.length - 1)
this.letter.text = _root.letter_array[index];
_x = Math.round(Math.random() * 540) + 5
_y = Math.round(Math.random() * -20) - 10;
var gravity = 0.2;
var ran = Math.round(Math.random() * 50) + 50;
_alpha = ran + 10;
_xscale = _yscale = ran;
speed = Math.round(Math.random() * 5) + 10;
rotSpeed = Math.round(Math.random() * 6) - 3;
//this.letter.textColor = Math.random() * 0xFFFFFF
}
onClipEvent(enterFrame)
{
_y += speed;
_rotation += rotSpeed
speed += gravity;
if(_y > 410)
{
this.removeMovieClip();
}
}
You need to add this at the top of your code:
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.events.*;
In the layer script you need to have an array of images, so the first thing would be to load all your images and store them in an array when the loading is complete.
in the following code , replace i "inferior to" totalNumImages with
i < totalNumImages , I can't use the "<" character in the code.
//your images location
var url1:String = "images/image1.jpg";
var url2:String = "images/image2.jpg";
var urls:Array = [ url1 , url2 ];
var images:Array = [];
//the total number of images
var totalNumImages:int = 2;
for(var i:int ;i "inferior to" totalNumImages ; ++i )
{
loadImage(images[i] );
}
function loadImage(url:String):void
{
var loader:Loader = new Loader();
var info:LoaderInfo = loader.contentLoaderInfo;
info.addEventListener(Event.COMPLETE , loadComplete );
info.addEventListener(IOErrorEvent.IO_ERROR , errorHandler );
loader.load ( new URLRequest(url ));
}
function errorHandler(event:IOErrorEvent):void
{
trace( event );
}
function loadComplete(event:Event):void
{
//assuming the order doesn't matter
images.push(event.currentTarget.loader.content );
//all images are loaded, let's start...
if(images.length == totalNumImages )
nLetter();
}
After all your images have loaded you can start the nLetter() function. Each time a MovieClip is added to the stage, it will load its image from the array of images that you've created.
change this:
this.letter.text = _root.letter_array[index];
to this:
//assumes that you have an array of DisplayObject
addChild( _root.images[index]);

Resources