I'm trying to refresh this AnyChart function div every 3 seconds, so that when data is entered using the (hopefully) interactive wordcloud on a wesbite, it refreshes automatcially. My code currently duplicates the div once, 3 seconds after the page loads. Thanks in advance for any help.
anychart.onDocumentReady(function() {
anychart.data.loadGoogleSpreadsheet({
key: '14jdnD4rzxPdZfLqpeh4gjtoN6ERyZuovBOoFOwuZQAM',
sheet: '2'
}, function(data) {
var chart = anychart.tagCloud();
// configure a color scale here
var customColorScale = anychart.scales.linearColor();
customColorScale.colors(["#FEBF57", "#428A46", "#21C5B4", "#E7438A", "#21295E"]);
// set the color scale as the color scale of the chart
chart.colorScale(customColorScale);
// add a color range
chart.colorRange().enabled(true);
chart.normal().fontFamily("Rubik", "sans-serif");
// set data
chart.data(data);
chart.container('wordcloud-container');
chart.draw();
});
});
$(document).ready(function() {
function refresh() {
var div = $('#wordcloud-container'),
divHtml = div.html();
div.html(divHtml);
}
setInterval(function() {
refresh()
}, 3000);
})
<h1>TEST WordCloud with colours</h1>
<div id='wordcloud-container'>
The issue is because your refresh() function simply gets the existing HTML of the container and then sets that same HTML within the container again, duplicating the content.
To actually refresh the chart you need to call loadGoogleSpreadsheet() from within the interval handler.
An important change to make here is to use setTimeout() within the chart callback instead of setInterval(). The latter can end up queueing requests if the response is slow, which can lead to your site becoming unresponsive due to too many in-progress requests. The setTimeout() approach will only start the timer when the previous request was successfully handled.
let loadChartData = () => {
console.log('loading data...');
anychart.data.loadGoogleSpreadsheet({
key: '14jdnD4rzxPdZfLqpeh4gjtoN6ERyZuovBOoFOwuZQAM',
sheet: '2'
}, function(data) {
var chart = anychart.tagCloud();
// configure a color scale here
var customColorScale = anychart.scales.linearColor();
customColorScale.colors(["#FEBF57", "#428A46", "#21C5B4", "#E7438A", "#21295E"]);
// set the color scale as the color scale of the chart
chart.colorScale(customColorScale);
// add a color range
chart.colorRange().enabled(true);
chart.normal().fontFamily("Rubik", "sans-serif");
// set data
chart.data(data);
$('#wordcloud-container').empty(); // important change here to stop duplicating the chart
chart.container('wordcloud-container');
chart.draw();
setTimeout(loadChartData, 3000);
});
}
$(document).ready(function() {
loadChartData();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.8.0/js/anychart-bundle.min.js"></script>
<link rel="stylesheet" href="https://cdn.anychart.com/releases/8.8.0/css/anychart-ui.min.css" />
<h1>TEST WordCloud with colours</h1>
<div id='wordcloud-container'></div>
One big issue to note here is that your approach of AJAX polling is not at all scalable. If this is implemented in a production system you will most likely hit rate limits on the Google docs API, or even be blocked for a potential DDOS risk.
Related
I would like to try the ml5.js Pix2Pix example for p5.js. If I just copy the code, update the paths, and try to let it run on my local server, it doesn't work.
Same here:
// Copyright (c) 2019 ml5
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
/* ===
ml5 Example
Pix2pix Edges2Pikachu example with p5.js using callback functions
This uses a pre-trained model on Pikachu images
For more models see: https://github.com/ml5js/ml5-data-and-training/tree/master/models/pix2pix
=== */
// The pre-trained Edges2Pikachu model is trained on 256x256 images
// So the input images can only be 256x256 or 512x512, or multiple of 256
const SIZE = 256;
let inputImg, inputCanvas, outputContainer, statusMsg, pix2pix, clearBtn, transferBtn, modelReady = false,
isTransfering = false;
function setup() {
// Create a canvas
inputCanvas = createCanvas(SIZE, SIZE);
inputCanvas.class('border-box').parent('canvasContainer');
// Display initial input image
inputImg = loadImage('https://ml5js.github.io/ml5-examples/javascript/Pix2Pix/Pix2Pix_promise/images/input.png', drawImage);
// Selcect output div container
outputContainer = select('#output');
statusMsg = select('#status');
// Select 'transfer' button html element
transferBtn = select('#transferBtn');
// Select 'clear' button html element
clearBtn = select('#clearBtn');
// Attach a mousePressed event to the 'clear' button
clearBtn.mousePressed(function() {
clearCanvas();
});
// Set stroke to black
stroke(0);
pixelDensity(1);
// Create a pix2pix method with a pre-trained model
pix2pix = ml5.pix2pix('https://github.com/ml5js/ml5-library/blob/main/examples/p5js/Pix2Pix/Pix2Pix_callback/models/edges2pikachu.pict', modelLoaded);
}
// Draw on the canvas when mouse is pressed
function draw() {
if (mouseIsPressed) {
line(mouseX, mouseY, pmouseX, pmouseY);
}
}
// Whenever mouse is released, transfer the current image if the model is loaded and it's not in the process of another transformation
function mouseReleased() {
if (modelReady && !isTransfering) {
transfer()
}
}
// A function to be called when the models have loaded
function modelLoaded() {
// Show 'Model Loaded!' message
statusMsg.html('Model Loaded!');
// Set modelReady to true
modelReady = true;
// Call transfer function after the model is loaded
transfer();
// Attach a mousePressed event to the transfer button
transferBtn.mousePressed(function() {
transfer();
});
}
// Draw the input image to the canvas
function drawImage() {
image(inputImg, 0, 0);
}
// Clear the canvas
function clearCanvas() {
background(255);
}
function transfer() {
// Set isTransfering to true
isTransfering = true;
// Update status message
statusMsg.html('Applying Style Transfer...!');
// Select canvas DOM element
const canvasElement = select('canvas').elt;
// Apply pix2pix transformation
pix2pix.transfer(canvasElement, function(err, result) {
if (err) {
console.log(err);
}
if (result && result.src) {
// Set isTransfering back to false
isTransfering = false;
// Clear output container
outputContainer.html('');
// Create an image based result
createImg(result.src).class('border-box').parent('output');
// Show 'Done!' message
statusMsg.html('Done!');
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.dom.min.js"></script>
<script src="https://unpkg.com/ml5#latest/dist/ml5.min.js" type="text/javascript"></script>
<h1>Pix2Pix Edges2Pichaku Example</h1>
<p>1. Wait until the model is loaded</p>
<p>2. Press your mouse to draw a Pikachu on the left side of the canvas.</p>
<p>3. A colored Pikachu image will automatically appear on the right side of the canvas in ~2 seconds. You could also click the "Transfer" button to generate an new image.</p>
<p>4. You could click the "Clear" button to clear the canvas and draw again.</p>
<p id="status">Loading Model... Please wait...</p>
<div class="flex">
<div>
<div id="canvasContainer"></div>
<div id="btnContainer" class="flex flex-space-between">
<button id="clearBtn">Clear</button><br />
<button id="transferBtn" class="btn">Transfer</button>
</div>
</div>
<div id="transferContainer">
</div>
<div id="output"></div>
</div>
Here would be also a jsFiddle:
https://jsfiddle.net/L6oaydrm/
Has anyone an idea how to let it run? Would be very thankful.
I think I was able to get the 'callback' example to work locally with some tinkering:
Download files from the example: https://github.com/ml5js/ml5-library/tree/main/examples/p5js/Pix2Pix/Pix2Pix_callback
Adjust the index.html to load ml5.min.js from the unpkg.com URL in your code.
Create a new function:
function startTransfer(){
// Create a pix2pix method with a pre-trained model
pix2pix = ml5.pix2pix('./models/edges2pikachu.pict', modelLoaded);
}
Replace all calls to transfer() except the first one in modelLoaded() with startTransfer().
Start a simple local web server; for me: python -m http.server worked.
The example appeared to work. I could draw on the canvas, and the ML model would redraw the Pikachu image factoring in the new lines I added. Note, sometimes the initial transfer is run before the template image (input.png) is loaded, and the result is a garbled yellow / red pixels; clicking 'Transfer' fixes this.
Basically, it always will reload the model into the ml5 library; I don't know of the performance implications of this, but it was redrawing relatively quickly in my browser. The file will be cached in the browser, so that isn't a concern, but I'm not sure of the internals of the ml5.js lib and what ml5.pix2pix(...) does.
I've put my revised code (including some other tweaks to the JS) up on https://jsfiddle.net/lecrte/jvohcw8r/16/ ... but it won't work there because the assets aren't available relative to the HTML file, and we can't load the edges2pikachu.pict direct from github.com due to CORS issues.
I would like to add a Progress Bar to my map in the following manner: http://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld.50000.html
The problem is that I am using children featureGroups in a parent cluster group, so that I can remove and add layers easily while keeping my clusters displayed.
I have tried the following two methods:
Leaflet.MarkerCluster.LayerSupport: the loading bar does not work at all when I try:
var mcgLayerSupportGroup = L.markerClusterGroup.layerSupport({ chunkedLoading: true,
chunkProgress: updateProgressBar});
Leaflet.FeatureGroup.SubGroup: the loading bar is displayed, but not for the overall markers added. Instead it is computed for each marker subgroup. The loading bar may disappear, then appear again, etc.
var parentGroup = L.markerClusterGroup({ chunkedLoading: true,
chunkProgress: updateProgressBar});
My best attempt so far has been to tweak the updateProgressBar, but my code is far from being effective (slow and approximate the behavior of a progress bar):
var tot_processed=0;
//this total_markers variable is computed when I call my API endpoints and compute the total number of markers
var total_markers;
function updateProgressBar(processed, total, elapsed, layersArray) {
tot_processed += processed;
if (total_trees - tot_processed > 1000) {
progress.style.display = 'block';
progressBar.style.width = Math.round(tot_processed/total_trees*100) + '%';
} else {
if (processed === total) {
// all markers processed - hide the progress bar:
progress.style.display = 'none';
}
}
}
Thank you very much!
about month ago i asked how to quee animatations for objects in Fabric.js to which i got response from #nickvans. This is the code. Based on this I changed the code and created with HTML5 drag and drop, aplication which allows you to give to each object on canvas its own set of different commands. Basicly creating moving scene. Mine 1st question is :if it is possible to also use sprites. So instead of the triangle in the exmaple below it would be animated sprite that would also change its position. And 2nd question is it possible to somehow add text field that would follow the object during its movement? Something like those comics bubles.
Thanks in advance for any tips
function startAnimationQueue(animationQueue){
// queues up the animations for the shape
var runningDuration = 0; // variable that adds up the animationQueue durations
for (var i=0; i<animationQueue.length; i++){
var animationDefinition = animationQueue[i];
// Create a closure around the animationDefiniton so that each setTimeout gets sequential animationDefinition inputs
var fn = (function(animationDefinition){
return function(){
triangle.animate('left', animationDefinition.left, {duration: animationDefinition.duration, onChange:canvas.renderAll.bind(canvas)})
triangle.animate('top', animationDefinition.top, {duration: animationDefinition.duration, onChange:canvas.renderAll.bind(canvas)})
// Note: you can animate additional attributes here if you want, just add additional attributes to the objects in
// the animationQueue list. You could also have one of those inputs be the object to be animated in case you want
// to animate multiple objects using the same queue.
};
})
// Create the timeout that will apply the transformations sequentially
// If you want you could set the window.setTimeout to a variable that you could destroy if you need
// to interrupt the animation queue after you create it (but before it finishes)
window.setTimeout(fn(animationDefinition), runningDuration);
// set the next setTimeout duration to be .duration later than the previous one
// this makes the second animation fire after the first one completes
runningDuration += animationDefinition.duration;
}
}
document.onreadystatechange = function () {
if (document.readyState == "complete") {
// I put the canvas init stuff in here because of (I think) a failed race condition or something that caused
// your original method to fail in Chrome
window.canvas = new fabric.Canvas('scene');
window.triangle = new fabric.Triangle({
width: 30
, height: 30
, fill: 'red'
, left: 30
, top: 0
});
window.canvas.add(window.triangle);
window.canvas.renderAll();
// Create a list of animations to apply
var animationQueue = [
{"left": "+=0", "top": "+=100", "duration": 1000},
{"left": "+=55", "top": "+=0", "duration": 2000}
]
// Apply the animations in sequence using window.setTimeout
startAnimationQueue(animationQueue);
}
}
and HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.0/fabric.min.js"></script>
</head>
<body>
<canvas id="scene" width="400" height="400" />
</body>
</html>
I am using QRTEngine in qualtrics. I have a problem with hiding the Init and the Exit part, here is what I have tried to do so far:
Init:
QRTE.Init({
// should correspond with Embedded Data field names
blockData: ‘${e://Field/QRTE_blockData}’,
idData: ‘${e://Field/QRTE_idData}’,
columnData: ‘${e://Field/QRTE_columns}’,
exitQuestions: ‘${e://Field/QRTE_exitQuestions}’,
exitItemTag: ‘ExitQ’, // DO NOT FORGET TO CHANGE FOR NEW BLOCKS
blockId: ‘Deafult Question Block’, // DO NOT FORGET TO CHANGE FOR NEW BLOCKS
onLoadFn: function() {
// set trial configuration for the screens
QRTE.setConfig(‘Smiley’, ‘duration’, 2000);
QRTE.setConfig(‘StroopItem’, ‘duration’, 6000);
QRTE.setConfig(‘StroopItem’, ‘allowable’, ‘xm’);
QRTE.setConfig(‘StroopItem’, ‘EndAction’, ‘TERMINATE’);
// save trial configurations for later analysis
QRTE.setTrialData(‘StimulusSimely’, ‘${lm://Field/1}’);
QRTE.setTrialData(‘Piconright’, ‘${lm://Field/2}’);
QRTE.setTrialData(‘Piconleft’, ‘${lm://Field/3}’);
this.questionContainer.style.display = ‘none';
},
interTrialDelay: [1000] // set interTrialDelay
});
onLoadFn: (function()
{
this.questionContainer.style.display = ‘none';
});
Exit:
QRTE.Exit();
Qualtrics.SurveyEngine.addOnload(function()
{
this.questionContainer.style.display = ‘none';
});
My goal would be to prevent the engine from displaying these questions.
I have tried to set the intertrialdelay to 0, but in that case the whole experiment became a mess.
Is it possible to animate the size of the header in a HeaderFooterLayout? I am trying to change it's size with an animation but I am not seeing any API for this. So I was wondering about a technique for doing it.
You can achieve this by using a Transitionable. This is done by the following:
Create a transition for the animation:
var transition = {
duration: 400,
curve: Easing.inOutQuad
};
Set the start & end pixel counts:
var start = open ? 200 : 100;
var end = open ? 100 : 200;
Instantiate your new Transitionable with the starting pixel count:
var transitionable = new Transitionable(start);
Create the function that will be executed to apply the pixel count:
var prerender = function () {
layout.setOptions({
headerSize: transitionable.get()
})
};
Attache the function to the Engine event:
Engine.on('prerender', prerender);
Add transition to end state to the queue of pending transitions:
transitionable.set(end, transition, complete);
Here is a working fiddle for you to reference: http://jsfiddle.net/Mabuti/4or8nxh4/
In full disclosure I did use the following post as a point of reference: famo.us: can I animate the header/footer heights of a header footer layout? but I tried to add some context to the process.
You could also review the Transitionable documentation to see better understand what it is doing: https://famo.us/docs/transitions/Transitionable
An alternative could be to use the famous-flex LayoutController and HeaderFooterLayout.
The code is pretty straightforward:
var LayoutController = require('famous-flex/LayoutController');
var HeaderFooterLayout = require('famous-flex/layouts/HeaderFooterLayout');
// Create header/content surface/views
var header = new Surface(..);
var content = new Surface(..);
// Create header-footer layout
var layout = new LayoutController({
layout: HeaderFooterLayout,
layoutOptions: {
headerSize: 40
},
flow: true, // this causes a smooth transition when changing the header-size
reflowOnResize: false, // do not reflow on resize
dataSource: {
header: header,
content: content
}
});
...
// Change the height of the header (because flow is enabled,
// this will automatically cause it to smoothly animate from
// the old height to the new height)
layout.setLayoutOptions({
headerSize: 100
});
Library: https://github.com/IjzerenHein/famous-flex