123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8">
- <title>Blockly Demo: Graph</title>
- <script src="https://www.google.com/jsapi"></script>
- <script src="../../blockly_compressed.js"></script>
- <script src="../../blocks_compressed.js"></script>
- <script src="../../javascript_compressed.js"></script>
- <script src="../../msg/js/en.js"></script>
- <style>
- body {
- background-color: #fff;
- font-family: sans-serif;
- }
- h1 {
- font-weight: normal;
- font-size: 140%;
- }
- #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>
- <h1><a href="https://developers.google.com/blockly/">Blockly</a> >
- <a href="../index.html">Demos</a> > Graph</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/guides/configure/web/code-generators#generating_code">Realtime generation</a>…</p>
- <table>
- <tr>
- <td>
- <div id="visualization" style="width: 400px"></div>
- </td>
- <td>
- <div id="blocklyDiv" style="height: 400px"></div>
- </td>
- </tr>
- </table>
- <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">
- <value name="A">
- <shadow type="math_number">
- <field name="NUM">1</field>
- </shadow>
- </value>
- <value name="B">
- <shadow type="math_number">
- <field name="NUM">1</field>
- </shadow>
- </value>
- </block>
- <block type="math_single">
- <value name="NUM">
- <shadow type="math_number">
- <field name="NUM">9</field>
- </shadow>
- </value>
- </block>
- <block type="math_trig">
- <value name="NUM">
- <shadow type="math_number">
- <field name="NUM">45</field>
- </shadow>
- </value>
- </block>
- <block type="math_constant"></block>
- <block type="math_number_property">
- <value name="NUMBER_TO_CHECK">
- <shadow type="math_number">
- <field name="NUM">0</field>
- </shadow>
- </value>
- </block>
- <block type="math_round">
- <value name="NUM">
- <shadow type="math_number">
- <field name="NUM">3.1</field>
- </shadow>
- </value>
- </block>
- <block type="math_modulo">
- <value name="DIVIDEND">
- <shadow type="math_number">
- <field name="NUM">64</field>
- </shadow>
- </value>
- <value name="DIVISOR">
- <shadow type="math_number">
- <field name="NUM">10</field>
- </shadow>
- </value>
- </block>
- <block type="math_constrain">
- <value name="VALUE">
- <shadow type="math_number">
- <field name="NUM">50</field>
- </shadow>
- </value>
- <value name="LOW">
- <shadow type="math_number">
- <field name="NUM">1</field>
- </shadow>
- </value>
- <value name="HIGH">
- <shadow type="math_number">
- <field name="NUM">100</field>
- </shadow>
- </value>
- </block>
- <block type="math_random_int">
- <value name="FROM">
- <shadow type="math_number">
- <field name="NUM">1</field>
- </shadow>
- </value>
- <value name="TO">
- <shadow type="math_number">
- <field name="NUM">100</field>
- </shadow>
- </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>
- <shadow type="math_number">
- <field name="NUM">1</field>
- </shadow>
- </value>
- <value name="B">
- <block type="math_number">
- <field name="NUM">2</field>
- </block>
- <shadow type="math_number">
- <field name="NUM">1</field>
- </shadow>
- </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.jsonInit({
- "message0": "x",
- "output": "Number",
- "colour": Blockly.Blocks.variables.HUE,
- "tooltip": Blockly.Msg.VARIABLES_GET_TOOLTIP,
- "helpUrl": Blockly.Msg.VARIABLES_GET_HELPURL
- });
- }
- };
- 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.jsonInit({
- "message0": "y = %1",
- "args0": [
- {
- "type": "input_value",
- "name": "VALUE",
- "check": "Number"
- }
- ],
- "colour": Blockly.Blocks.variables.HUE,
- "tooltip": Blockly.Msg.VARIABLES_SET_TOOLTIP,
- "helpUrl": Blockly.Msg.VARIABLES_SET_HELPURL
- });
- }
- };
- Blockly.JavaScript['graph_set_y'] = function(block) {
- // y variable setter.
- var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
- Blockly.JavaScript.ORDER_ASSIGNMENT) || '';
- return 'y = ' + argument0 + ';';
- };
- /**
- * Create a namespace for the application.
- */
- var Graph = {};
- /**
- * Main Blockly workspace.
- * @type {Blockly.WorkspaceSvg}
- */
- Graph.workspace = null;
- /**
- * 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 formula = Blockly.JavaScript.workspaceToCode(Graph.workspace);
- 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(formula));
- // Create and draw the visualization, passing in the data and options.
- new google.visualization.LineChart(document.getElementById('visualization')).
- draw(data, Graph.options_);
- // Create the "y = ..." label. Find the relevant part of the code.
- formula = formula.substring(formula.indexOf('y = '));
- formula = formula.substring(0, formula.indexOf(';'));
- var funcText = document.getElementById('funcText');
- funcText.replaceChild(document.createTextNode(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 {
- 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;
- };
- /**
- * Force Blockly to resize into the available width.
- */
- Graph.resize = function() {
- var width = Math.max(window.innerWidth - 440, 250);
- document.getElementById('blocklyDiv').style.width = width + 'px';
- Blockly.svgResize(Graph.workspace);
- };
- /**
- * Initialize Blockly and the graph. Called on page load.
- */
- Graph.init = function() {
- Graph.workspace = Blockly.inject('blocklyDiv',
- {collapse: false,
- disable: false,
- media: '../../media/',
- toolbox: document.getElementById('toolbox')});
- Blockly.Xml.domToWorkspace(document.getElementById('startBlocks'),
- Graph.workspace);
- Graph.workspace.clearUndo();
- // When Blockly changes, update the graph.
- Graph.workspace.addChangeListener(Graph.drawVisualization);
- Graph.workspace.addChangeListener(Blockly.Events.disableOrphans);
- Graph.resize();
- };
- window.addEventListener('load', Graph.init);
- window.addEventListener('resize', Graph.resize);
- </script>
- </body>
- </html>
|