display of the blocks as SVG in instruction-component

This commit is contained in:
Delucse 2020-09-27 20:15:11 +02:00
parent 5044b09701
commit 9d99c5c30b
8 changed files with 115 additions and 53 deletions

View File

@ -1,7 +0,0 @@
#blocklyDiv {
height: 100%;
min-height: 500px;
width: 100%;
/* border: 1px solid #4EAF47; */
position: relative;
}

View File

@ -22,7 +22,6 @@
*/ */
import React from 'react'; import React from 'react';
import './BlocklyComponent.css';
import Blockly from 'blockly/core'; import Blockly from 'blockly/core';
import locale from 'blockly/msg/en'; import locale from 'blockly/msg/en';

View File

@ -0,0 +1,65 @@
import React, { Component } from 'react';
import * as Blockly from 'blockly/core';
class BlocklySvg extends Component {
constructor(props) {
super(props);
this.state = {
svg: ''
};
}
componentDidMount() {
this.getSvg();
}
componentDidUpdate(props) {
if(props.initialXml !== this.props.initialXml){
this.getSvg();
}
}
getSvg = () => {
const workspace = Blockly.getMainWorkspace();
workspace.clear();
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(this.props.initialXml), workspace);
var canvas = workspace.svgBlockCanvas_.cloneNode(true);
if (canvas.children[0] !== undefined) {
canvas.removeAttribute("transform");
// does not work in react
// var cssContent = Blockly.Css.CONTENT.join('');
var cssContent = '';
for (var i = 0; i < document.getElementsByTagName('style').length; i++) {
if(/^blockly.*$/.test(document.getElementsByTagName('style')[i].id)){
cssContent += document.getElementsByTagName('style')[i].firstChild.data.replace(/\..* \./g, '.');
}
}
var css = '<defs><style type="text/css" xmlns="http://www.w3.org/1999/xhtml"><![CDATA[' + cssContent + ']]></style></defs>';
var bbox = document.getElementsByClassName("blocklyBlockCanvas")[0].getBBox();
var content = new XMLSerializer().serializeToString(canvas);
var xml = `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="${bbox.width}" height="${bbox.height}" viewBox="${bbox.x} ${bbox.y} ${bbox.width} ${bbox.height}">
${css}">${content}</svg>`;
this.setState({svg: xml});
}
}
render() {
return (
<div
style={{display: 'flex', justifyContent: 'center', transform: 'scale(0.8) translate(0, calc(100% * -0.2 / 2))'}}
dangerouslySetInnerHTML={{ __html: this.state.svg }}
/>
);
};
}
export default BlocklySvg;

View File

@ -3,7 +3,8 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { onChangeWorkspace, clearStats } from '../../actions/workspaceActions'; import { onChangeWorkspace, clearStats } from '../../actions/workspaceActions';
import * as De from './msg/de'; import * as De from './msg/de';
import BlocklyComponent from './'; import BlocklyComponent from './BlocklyComponent';
import BlocklySvg from './BlocklySvg';
import * as Blockly from 'blockly/core'; import * as Blockly from 'blockly/core';
import './blocks/index'; import './blocks/index';
import './generator/index'; import './generator/index';
@ -32,49 +33,52 @@ class BlocklyWindow extends Component {
componentDidUpdate(props) { componentDidUpdate(props) {
const workspace = Blockly.getMainWorkspace(); const workspace = Blockly.getMainWorkspace();
var initialXML = this.props.initialXml var xml = this.props.initialXml
if(props.initialXml !== initialXml){ // if svg is true, then the update process is done in the BlocklySvg component
if(props.initialXml !== xml && !this.props.svg){
// guarantees that the current xml-code (this.props.initialXml) is rendered // guarantees that the current xml-code (this.props.initialXml) is rendered
workspace.clear(); workspace.clear();
if(!initialXML) initialXML = initialXml; if(!xml) xml = initialXml;
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(initialXML), workspace) ; Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xml), workspace);
} }
Blockly.svgResize(workspace); Blockly.svgResize(workspace);
} }
render() { render() {
return ( return (
<BlocklyComponent ref={this.simpleWorkspace} <div>
style={this.props.blocklyCSS} <BlocklyComponent ref={this.simpleWorkspace}
readOnly={this.props.readOnly !== undefined ? this.props.readOnly : false} style={this.props.svg ? {height: 0} : this.props.blocklyCSS}
trashcan={this.props.trashcan !== undefined ? this.props.trashcan : true} readOnly={this.props.readOnly !== undefined ? this.props.readOnly : false}
renderer='zelos' trashcan={this.props.trashcan !== undefined ? this.props.trashcan : true}
zoom={{ // https://developers.google.com/blockly/guides/configure/web/zoom renderer='zelos'
controls: this.props.zoomControls !== undefined ? this.props.zoomControls : true, zoom={{ // https://developers.google.com/blockly/guides/configure/web/zoom
wheel: false, controls: this.props.zoomControls !== undefined ? this.props.zoomControls : true,
startScale: 0.8, wheel: false,
maxScale: 3, startScale: 0.8,
minScale: 0.3, maxScale: 3,
scaleSpeed: 1.2 minScale: 0.3,
}} scaleSpeed: 1.2
grid={this.props.grid !== undefined && !this.props.grid ? {} : }}
{ // https://developers.google.com/blockly/guides/configure/web/grid grid={this.props.grid !== undefined && !this.props.grid ? {} :
spacing: 20, { // https://developers.google.com/blockly/guides/configure/web/grid
length: 1, spacing: 20,
colour: '#4EAF47', // senseBox-green length: 1,
snap: false colour: '#4EAF47', // senseBox-green
}} snap: false
media={'/media/blockly/'} }}
move={this.props.move !== undefined && !this.props.move ? {} : media={'/media/blockly/'}
{ // https://developers.google.com/blockly/guides/configure/web/move move={this.props.move !== undefined && !this.props.move ? {} :
scrollbars: true, { // https://developers.google.com/blockly/guides/configure/web/move
drag: true, scrollbars: true,
wheel: false drag: true,
}} wheel: false
initialXml={this.props.initialXml ? this.props.initialXml : initialXml} }}
> initialXml={this.props.initialXml ? this.props.initialXml : initialXml}
>
</BlocklyComponent > </BlocklyComponent >
{this.props.svg && this.props.initialXml ? <BlocklySvg initialXml={this.props.initialXml}/> : null}
</div>
); );
}; };
} }

View File

@ -87,7 +87,7 @@ class Home extends Component {
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<TrashcanButtons /> <TrashcanButtons />
<BlocklyWindow /> <BlocklyWindow blocklyCSS={{height: '500px'}}/>
</Grid> </Grid>
{this.state.codeOn ? {this.state.codeOn ?
<Grid item xs={12} md={6}> <Grid item xs={12} md={6}>

View File

@ -39,7 +39,10 @@ class Assessment extends Component {
<div style={{float: 'right', height: '40px'}}><WorkspaceFunc solutionCheck/></div> <div style={{float: 'right', height: '40px'}}><WorkspaceFunc solutionCheck/></div>
<Grid container spacing={2} style={{marginBottom: '5px'}}> <Grid container spacing={2} style={{marginBottom: '5px'}}>
<Grid item xs={12} md={6} lg={8}> <Grid item xs={12} md={6} lg={8}>
<BlocklyWindow initialXml={statusTask ? statusTask.xml ? statusTask.xml : null : null}/> <BlocklyWindow
initialXml={statusTask ? statusTask.xml ? statusTask.xml : null : null}
blocklyCSS={{height: '500px'}}
/>
</Grid> </Grid>
<Grid item xs={12} md={6} lg={4} style={isWidthDown('sm', this.props.width) ? {height: 'max-content'} : {}}> <Grid item xs={12} md={6} lg={4} style={isWidthDown('sm', this.props.width) ? {height: 'max-content'} : {}}>
<Card style={{height: 'calc(50% - 30px)', padding: '10px', marginBottom: '10px'}}> <Card style={{height: 'calc(50% - 30px)', padding: '10px', marginBottom: '10px'}}>

View File

@ -114,7 +114,10 @@ class BlocklyExample extends Component {
<div style={{marginTop: '10px'}}> <div style={{marginTop: '10px'}}>
<Grid container className={!this.props.value || this.props.error ? this.props.classes.errorBorder : null}> <Grid container className={!this.props.value || this.props.error ? this.props.classes.errorBorder : null}>
<Grid item xs={12}> <Grid item xs={12}>
<BlocklyWindow initialXml={initialXml}/> <BlocklyWindow
initialXml={initialXml}
blocklyCSS={{height: '500px'}}
/>
</Grid> </Grid>
</Grid> </Grid>
<Button <Button

View File

@ -27,12 +27,7 @@ class Instruction extends Component {
<Grid container spacing={2} style={{marginBottom: '5px'}}> <Grid container spacing={2} style={{marginBottom: '5px'}}>
<Grid item xs={12}> <Grid item xs={12}>
<BlocklyWindow <BlocklyWindow
trashcan={false} svg
readOnly={true}
zoomControls={false}
grid={false}
move={false}
blocklyCSS={{minHeight: '300px'}}
initialXml={step.xml} initialXml={step.xml}
/> />
</Grid> </Grid>