mirror of
https://github.com/google/blockly.git
synced 2025-12-16 06:10:12 +01:00
Initial version of simplified Graph demo.
This commit is contained in:
300
demos/graph/index.html
Normal file
300
demos/graph/index.html
Normal file
@@ -0,0 +1,300 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Blockly Demo: Graphing Calculator</title>
|
||||
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
|
||||
<script type="text/javascript" src="../../blockly_compressed.js"></script>
|
||||
<script type="text/javascript" src="../../blocks_compressed.js"></script>
|
||||
<script type="text/javascript" src="../../javascript_compressed.js"></script>
|
||||
<script type="text/javascript" src="../../msg/js/en.js"></script>
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
background-color: #fff;
|
||||
font-family: sans-serif;
|
||||
overflow: hidden;
|
||||
}
|
||||
h1 {
|
||||
font-weight: normal;
|
||||
font-size: 140%;
|
||||
}
|
||||
#blocklyDiv {
|
||||
float: right;
|
||||
height: 95%;
|
||||
width: 70%;
|
||||
}
|
||||
#visualization {
|
||||
width: 400px;
|
||||
}
|
||||
#funcText {
|
||||
margin-top: 1em;
|
||||
margin-left: 1.5em;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
#funcText>img {
|
||||
height: 3px;
|
||||
width: 15px;
|
||||
vertical-align: middle;
|
||||
margin-right: .5em;
|
||||
}
|
||||
#y1 {
|
||||
background-color: #36c;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="blocklyDiv"></div>
|
||||
|
||||
<h1><a href="https://developers.google.com/blockly/">Blockly</a> >
|
||||
<a href="../index.html">Demos</a> > Graphing Calculator</h1>
|
||||
|
||||
<p>This is a demo of giving instant feedback as blocks are changed.</p>
|
||||
|
||||
<p>→ More info on <a href="https://developers.google.com/blockly/installation/code-generators#realtime_generation">Realtime generation</a>...</p>
|
||||
|
||||
<div id="visualization"></div>
|
||||
|
||||
<div id="funcText">
|
||||
<img id="y1" src="../../media/1x1.gif">
|
||||
...
|
||||
</div>
|
||||
|
||||
<xml id="toolbox" style="display: none">
|
||||
<category name="Math">
|
||||
<block type="math_number"></block>
|
||||
<block type="math_arithmetic"></block>
|
||||
<block type="math_single"></block>
|
||||
<block type="math_trig"></block>
|
||||
<block type="math_constant"></block>
|
||||
<block type="math_number_property"></block>
|
||||
<block type="math_round"></block>
|
||||
<block type="math_modulo"></block>
|
||||
<block type="math_constrain">
|
||||
<value name="LOW">
|
||||
<block type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="HIGH">
|
||||
<block type="math_number">
|
||||
<field name="NUM">100</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
<block type="math_random_int">
|
||||
<value name="FROM">
|
||||
<block type="math_number">
|
||||
<field name="NUM">1</field>
|
||||
</block>
|
||||
</value>
|
||||
<value name="TO">
|
||||
<block type="math_number">
|
||||
<field name="NUM">100</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
<block type="math_random_float"></block>
|
||||
</category>
|
||||
<category name="Variables">
|
||||
<block type="graph_get_x"></block>
|
||||
</category>
|
||||
<category name="Logic">
|
||||
<block type="logic_compare"></block>
|
||||
<block type="logic_operation"></block>
|
||||
<block type="logic_negate"></block>
|
||||
<block type="logic_boolean"></block>
|
||||
<block type="logic_ternary"></block>
|
||||
</category>
|
||||
</xml>
|
||||
|
||||
<xml id="startBlocks" style="display: none">
|
||||
<block type="graph_set_y" deletable="false" x="100" y="100">
|
||||
<value name="VALUE">
|
||||
<block type="math_arithmetic">
|
||||
<field name="OP">POWER</field>
|
||||
<value name="A">
|
||||
<block type="graph_get_x"></block>
|
||||
</value>
|
||||
<value name="B">
|
||||
<block type="math_number">
|
||||
<field name="NUM">2</field>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
</value>
|
||||
</block>
|
||||
</xml>
|
||||
|
||||
<script>
|
||||
// Load the Google Chart Tools Visualization API and the chart package.
|
||||
if (typeof google == 'object') {
|
||||
google.load('visualization', '1', {packages: ['corechart']});
|
||||
} else {
|
||||
alert('Unable to load Google\'s chart API.\n' +
|
||||
'Are you connected to the Internet?');
|
||||
}
|
||||
|
||||
// Define the custom blocks and their JS generators.
|
||||
Blockly.Blocks['graph_get_x'] = {
|
||||
// x variable getter.
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL);
|
||||
this.setColour(330);
|
||||
this.appendDummyInput()
|
||||
.appendField('x');
|
||||
this.setOutput(true, 'Number');
|
||||
this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP);
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.JavaScript['graph_get_x'] = function(block) {
|
||||
// x variable getter.
|
||||
return ['x', Blockly.JavaScript.ORDER_ATOMIC];
|
||||
};
|
||||
|
||||
Blockly.Blocks['graph_set_y'] = {
|
||||
// y variable setter.
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.VARIABLES_SET_HELPURL);
|
||||
this.setColour(330);
|
||||
this.appendValueInput('VALUE')
|
||||
.appendField('y =');
|
||||
this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP);
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.JavaScript['graph_set_y'] = function(block) {
|
||||
// y variable setter.
|
||||
var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
|
||||
Blockly.JavaScript.ORDER_ASSIGNMENT) || '';
|
||||
return argument0 + ';';
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a namespace for the application.
|
||||
*/
|
||||
var Graph = {};
|
||||
|
||||
/**
|
||||
* Cached copy of the function string.
|
||||
* @type ?string
|
||||
* @private
|
||||
*/
|
||||
Graph.oldFormula_ = null;
|
||||
|
||||
/**
|
||||
* Drawing options for the Chart API.
|
||||
* @type !Object
|
||||
* @private
|
||||
*/
|
||||
Graph.options_ = {
|
||||
//curveType: 'function',
|
||||
width: 400, height: 400,
|
||||
chartArea: {left: '10%', width: '85%', height: '85%'}
|
||||
};
|
||||
|
||||
/**
|
||||
* Visualize the graph of y = f(x) using Google Chart Tools.
|
||||
* For more documentation on Google Chart Tools, see this linechart example:
|
||||
* https://developers.google.com/chart/interactive/docs/gallery/linechart
|
||||
*/
|
||||
Graph.drawVisualization = function() {
|
||||
var tuple = Graph.getFunction();
|
||||
var defs = tuple[0];
|
||||
var formula = tuple[1];
|
||||
if (formula === Graph.oldFormula_) {
|
||||
// No change in the formula, don't recompute.
|
||||
return;
|
||||
}
|
||||
Graph.oldFormula_ = formula;
|
||||
|
||||
// Create and populate the data table.
|
||||
var data = google.visualization.arrayToDataTable(Graph.plot(defs + formula));
|
||||
// Create and draw the visualization, passing in the data and options.
|
||||
new google.visualization.LineChart(document.getElementById('visualization')).
|
||||
draw(data, Graph.options_);
|
||||
|
||||
// Remove the ";" generally ending the JavaScript statement y = {code};.
|
||||
formula = formula.replace(/;$/, '');
|
||||
var funcText = document.getElementById('funcText');
|
||||
funcText.replaceChild(document.createTextNode('y = ' + formula),
|
||||
funcText.lastChild);
|
||||
};
|
||||
|
||||
/**
|
||||
* Plot points on the function y = f(x).
|
||||
* @param {string} code JavaScript code.
|
||||
* @return {!Array.<!Array>} 2D Array of points on the graph.
|
||||
*/
|
||||
Graph.plot = function(code) {
|
||||
// Initialize a table with two column headings.
|
||||
var table = [];
|
||||
var y;
|
||||
// TODO: Improve range and scale of graph.
|
||||
for (var x = -10; x <= 10; x = Math.round((x + 0.1) * 10) / 10) {
|
||||
try {
|
||||
y = eval(code);
|
||||
} catch (e) {
|
||||
y = NaN;
|
||||
}
|
||||
if (!isNaN(y)) {
|
||||
// Prevent y from being displayed inconsistently, some in decimals, some
|
||||
// in scientific notation, often when y has accumulated rounding errors.
|
||||
y = Math.round(y * Math.pow(10, 14)) / Math.pow(10, 14);
|
||||
table.push([x, y]);
|
||||
}
|
||||
}
|
||||
// Add column heading to table.
|
||||
if (table.length) {
|
||||
table.unshift(['x', 'y']);
|
||||
} else {
|
||||
// If the table is empty, add a [0, 0] row to prevent graph error.
|
||||
table.unshift(['x', 'y'], [0, 0]);
|
||||
}
|
||||
return table;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get from blocks the right hand side content of the function y = f(x).
|
||||
* @return {!Array.<string>} Tuple of any function definitions and the formula
|
||||
* in JavaScipt for f(x).
|
||||
*/
|
||||
Graph.getFunction = function() {
|
||||
var topBlocks = Blockly.mainWorkspace.getTopBlocks(false);
|
||||
var yBlock;
|
||||
// Set yBlock to only the code plugged into 'graph_set_y'.
|
||||
for (var j = 0; j < topBlocks.length; j++) {
|
||||
if (topBlocks[j].type == 'graph_set_y') {
|
||||
yBlock = topBlocks[j];
|
||||
}
|
||||
}
|
||||
if (!yBlock) {
|
||||
return NaN;
|
||||
}
|
||||
Blockly.JavaScript.init();
|
||||
var code = Blockly.JavaScript.blockToCode(yBlock);
|
||||
var defs = Blockly.JavaScript.finish('');
|
||||
return [defs, code];
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize Blockly and the graph. Called on page load.
|
||||
*/
|
||||
Graph.init = function() {
|
||||
Blockly.inject(document.getElementById('blocklyDiv'),
|
||||
{toolbox: document.getElementById('toolbox')});
|
||||
Blockly.Xml.domToWorkspace(Blockly.mainWorkspace,
|
||||
document.getElementById('startBlocks'));
|
||||
|
||||
// When Blockly changes, update the graph.
|
||||
Blockly.addChangeListener(Graph.drawVisualization);
|
||||
}
|
||||
|
||||
window.addEventListener('load', Graph.init);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user