Published
Edited
Mar 22, 2021
3 forks
Importers
2 stars
Insert cell
Insert cell
Insert cell
BlocklyCanvasConstants = {
return {
BeginPath: 'beginpath',
ClosePath: 'closepath',
MoveTo: 'moveto',
LineTo: 'lineto',
Save: 'save',
Restore: 'restore',
Stroke: 'stroke',
Fill: 'fill',
Rect: 'rect',
Quad: 'quad',
Arc: 'arc',
Point: 'point',
Triangle: 'triangle',
BezierCurve: 'bezierCurve',
QuadraticCurve: 'quadraticCurve',
Ellipse: 'ellipse',
Text: 'text',
Image: 'image',
SetTransform: 'setTransform',
Transform: 'transform',
Translate: 'translate',
Scale: 'scale',
Clock: 'clock',
GlobalStyle: 'globalStyle',
};
}
Insert cell
Insert cell
function registerBlocklyCanvasExtensions(Blockly) {
const category = {
name: "画板",
kind: "category",
colour: 20,
contents: [
{
name: "全局",
kind: "category",
colour: 80,
contents: [
canvasGlobalStyle(Blockly),
]
},
{
name: "路径",
kind: "category",
colour: 120,
contents: [
canvasBeginPath(Blockly),
canvasClosePath(Blockly),
canvasMoveTo(Blockly),
canvasLineTo(Blockly)
]
},
{
name: "形状",
kind: "category",
colour: 160,
contents: [canvasRect(Blockly), canvasQuad(Blockly),
canvasTriangle(Blockly), canvasBlocklyArc(Blockly),
canvasPoint(Blockly), canvasEllipse(Blockly),
canvasBezierCurve(Blockly), canvasQuadraticCurve(Blockly),
canvasText(Blockly), canvasImage(Blockly),
canvasClock(Blockly)
]
},
{
name: "绘制",
kind: "category",
colour: 180,
contents: [canvasStroke(Blockly), canvasFill(Blockly)]
},
{
name: "变换",
kind: "category",
colour: 200,
contents: [canvasSave(Blockly), canvasSetTransform(Blockly),
canvasTransform(Blockly), canvasTranslate(Blockly),
canvasScale(Blockly), canvasRestore(Blockly)
]
}
]
};

return category;
}
Insert cell
Insert cell
md`### Global Style`
Insert cell
function canvasGlobalStyle(Blockly) {
const name = BlocklyCanvasConstants.GlobalStyle;

Blockly.Blocks[name] = {
init: function() {
this.appendDummyInput().appendField("全局样式")
this.appendValueInput("backgroundColor")
.setCheck("Colour")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("背景色");
this.appendValueInput("opacity")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("不透明度");
this.setInputsInline(false);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(25);
this.setTooltip("");
this.setHelpUrl();
}
};

Blockly.JavaScript[name] = function(block) {
let backgroundColor = Blockly.JavaScript.valueToCode(
block,
'backgroundColor',
Blockly.JavaScript.ORDER_NONE
);
let opacity = Blockly.JavaScript.valueToCode(
block,
'opacity',
Blockly.JavaScript.ORDER_NONE
);
let code = `
canvas.style.backgroundColor = ${backgroundColor};
canvas.style.opacity = ${opacity};
`;

return code;
};

return {
kind: "block",
blockxml: ` <block type="${name}">
<value name="backgroundColor">
<shadow type="colour_picker">
<field name="COLOUR">#000000</field>
</shadow>
</value>
<value name="opacity">
<shadow type="math_number">
<field name="NUM">0.5</field>
</shadow>
</value>
</block>`
};
}
Insert cell
Insert cell
function canvasBeginPath(Blockly) {
const name = BlocklyCanvasConstants.BeginPath;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("开始路径");
this.appendDummyInput()
.appendField("端点样式")
.appendField(
new Blockly.FieldDropdown([
["butt", "butt"],
["round", "round"],
["square", "square"]
]),
"lineCap"
);
this.appendDummyInput()
.appendField("折点样式")
.appendField(
new Blockly.FieldDropdown([
["miter", "miter"],
["round", "round"],
["bevel", "bevel"]
]),
"lineJoin"
);
this.appendValueInput("strokeStyle")
.setCheck("Colour")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("线条颜色");
this.appendValueInput("lineWidth")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("线条宽度");
this.appendValueInput("fillStyle")
.setCheck("Colour")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("填充颜色");
this.appendValueInput("transparency")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("透明度");
this.setInputsInline(false);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(10);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let dropdown_linecap = block.getFieldValue('lineCap');
let dropdown_linejoin = block.getFieldValue('lineJoin');
let value_strokestyle = Blockly.JavaScript.valueToCode(
block,
'strokeStyle',
Blockly.JavaScript.ORDER_NONE
);
let value_linewidth = Blockly.JavaScript.valueToCode(
block,
'lineWidth',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_fillstyle = Blockly.JavaScript.valueToCode(
block,
'fillStyle',
Blockly.JavaScript.ORDER_NONE
);
let transparency = Blockly.JavaScript.valueToCode(
block,
'transparency',
Blockly.JavaScript.ORDER_NONE
);

let code = `
context.lineCap = '${dropdown_linecap}';
context.lineJoin = '${dropdown_linejoin}';
context.strokeStyle = ${value_strokestyle};
context.lineWidth = ${value_linewidth};
context.fillStyle = ${value_fillstyle};
context.globalAlpha = ${transparency};
context.beginPath();
${next}`;
return code;
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="strokeStyle">
<shadow type="colour_picker">
<field name="COLOUR">#000000</field>
</shadow>
</value>
<value name="lineWidth">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="fillStyle">
<shadow type="colour_picker">
<field name="COLOUR">#000000</field>
</shadow>
</value>
<value name="transparency">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### ClosePath`
Insert cell
function canvasClosePath(Blockly) {
const name = BlocklyCanvasConstants.ClosePath;

Blockly.Blocks[name] = {
init: function() {
this.appendDummyInput().appendField("结束路径");
this.setInputsInline(false);
this.setOutput(true, null);
this.setColour(30);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/closePath");
}
};

Blockly.JavaScript[name] = function(block) {
let code = `
context.closePath();`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: ` <block type="${name}"></block>`
};
}
Insert cell
Insert cell
function canvasMoveTo(Blockly) {
const name = BlocklyCanvasConstants.MoveTo;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("移动到");
this.appendValueInput("X")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X");
this.appendValueInput("Y")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y");
this.setInputsInline(false);
this.setOutput(true, null);
this.setColour(50);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/moveTo");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x = Blockly.JavaScript.valueToCode(
block,
'X',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y = Blockly.JavaScript.valueToCode(
block,
'Y',
Blockly.JavaScript.ORDER_ATOMIC
);
// TODO: Assemble JavaScript into code variable.
let code = `
context.moveTo(${value_x},${value_y});
${next}`;
return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
<value name="Y">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
</block>`
};
}
Insert cell
Insert cell
function canvasLineTo(Blockly) {
const name = BlocklyCanvasConstants.LineTo;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("画直线");
this.appendValueInput("X")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X");
this.appendValueInput("Y")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y");
this.setInputsInline(false);
this.setOutput(true, null);
this.setColour(70);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineTo");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x = Blockly.JavaScript.valueToCode(
block,
'X',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y = Blockly.JavaScript.valueToCode(
block,
'Y',
Blockly.JavaScript.ORDER_ATOMIC
);

let code = `
context.lineTo(${value_x},${value_y});
${next}`;
return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="Y">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Save`
Insert cell
function canvasSave(Blockly) {
const name = BlocklyCanvasConstants.Save

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput('next').appendField("保存");
this.setInputsInline(false);
this.setOutput(true, null);
this.setColour(90);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save");
}
};

Blockly.JavaScript['save'] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let code = `
context.save();
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: ` <block type="${name}"></block>`
};
}
Insert cell
md`### Restore`
Insert cell
function canvasRestore(Blockly) {
const name = BlocklyCanvasConstants.Restore;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput('next').appendField("还原");
this.setInputsInline(false);
this.setOutput(true, null);
this.setColour(110);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore");
}
};

Blockly.JavaScript['restore'] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let code = `
context.restore();
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: ` <block type="${name}"></block>`
};
}
Insert cell
Insert cell
function canvasStroke(Blockly) {
const name = BlocklyCanvasConstants.Stroke;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput('next').appendField("描绘");
this.setInputsInline(false);
this.setOutput(true, null);
this.setColour(130);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/stroke");
}
};

Blockly.JavaScript['stroke'] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let code = `
context.stroke();
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: ` <block type="${name}"></block>`
};
}
Insert cell
md`### Fill`
Insert cell
function canvasFill(Blockly) {
const name = BlocklyCanvasConstants.Fill;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput('next').appendField("填充");
this.setInputsInline(false);
this.setOutput(true, null);
this.setColour(150);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fill");
}
};

Blockly.JavaScript['fill'] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let code = `
context.fill();
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: ` <block type="${name}"></block>`
};
}
Insert cell
Insert cell
function canvasRect(Blockly) {
const name = BlocklyCanvasConstants.Rect;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("矩形");
this.appendValueInput("X1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X1");
this.appendValueInput("Y1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y1");
this.appendValueInput("X2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X2");
this.appendValueInput("Y2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y2");
this.setOutput(true, null);
this.setColour(170);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/rect");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x1 = Blockly.JavaScript.valueToCode(
block,
'X1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y1 = Blockly.JavaScript.valueToCode(
block,
'Y1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x2 = Blockly.JavaScript.valueToCode(
block,
'X2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y2 = Blockly.JavaScript.valueToCode(
block,
'Y2',
Blockly.JavaScript.ORDER_ATOMIC
);

let code = `
context.rect(${value_x1},${value_y1},${value_x2},${value_y2});
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X1">
<shadow type="math_number">
<field name="NUM">20</field>
</shadow>
</value>
<value name="Y1">
<shadow type="math_number">
<field name="NUM">20</field>
</shadow>
</value>
<value name="X2">
<shadow type="math_number">
<field name="NUM">160</field>
</shadow>
</value>
<value name="Y2">
<shadow type="math_number">
<field name="NUM">140</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Quad`
Insert cell
function canvasQuad(Blockly) {
const name = BlocklyCanvasConstants.Quad;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("四边形");
this.appendValueInput("X1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X1");
this.appendValueInput("Y1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y1");
this.appendValueInput("X2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X2");
this.appendValueInput("Y2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y2");
this.appendValueInput("X3")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X3");
this.appendValueInput("Y3")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y3");
this.appendValueInput("X4")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X4");
this.appendValueInput("Y4")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y4");
this.setOutput(true, null);
this.setColour(175);
this.setTooltip("");
this.setHelpUrl("");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x1 = Blockly.JavaScript.valueToCode(
block,
'X1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y1 = Blockly.JavaScript.valueToCode(
block,
'Y1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x2 = Blockly.JavaScript.valueToCode(
block,
'X2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y2 = Blockly.JavaScript.valueToCode(
block,
'Y2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x3 = Blockly.JavaScript.valueToCode(
block,
'X3',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y3 = Blockly.JavaScript.valueToCode(
block,
'Y3',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x4 = Blockly.JavaScript.valueToCode(
block,
'X4',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y4 = Blockly.JavaScript.valueToCode(
block,
'Y4',
Blockly.JavaScript.ORDER_ATOMIC
);

let code = `
context.moveTo(${value_x1}, ${value_y1});
context.lineTo(${value_x2}, ${value_y2});
context.lineTo(${value_x3}, ${value_y3});
context.lineTo(${value_x4}, ${value_y4});
context.lineTo(${value_x1}, ${value_y1});
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X1">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="Y1">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="X2">
<shadow type="math_number">
<field name="NUM">80</field>
</shadow>
</value>
<value name="Y2">
<shadow type="math_number">
<field name="NUM">250</field>
</shadow>
</value>
<value name="X3">
<shadow type="math_number">
<field name="NUM">250</field>
</shadow>
</value>
<value name="Y3">
<shadow type="math_number">
<field name="NUM">300</field>
</shadow>
</value>
<value name="X4">
<shadow type="math_number">
<field name="NUM">160</field>
</shadow>
</value>
<value name="Y4">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Point`
Insert cell
function canvasPoint(Blockly) {
const name = BlocklyCanvasConstants.Point;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("圆点");
this.appendValueInput("startX")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X");
this.appendValueInput("startY")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y");
this.appendValueInput("R")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("R");
this.appendValueInput("fillStyle")
.setCheck("Colour")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("颜色");
this.setOutput(true, null);
this.setColour(185);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_startx = Blockly.JavaScript.valueToCode(
block,
'startX',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_starty = Blockly.JavaScript.valueToCode(
block,
'startY',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_r = Blockly.JavaScript.valueToCode(
block,
'R',
Blockly.JavaScript.ORDER_ATOMIC
);
let fillStyle = Blockly.JavaScript.valueToCode(
block,
'fillStyle',
Blockly.JavaScript.ORDER_ATOMIC
);

let code = `
context.arc(${value_startx}, ${value_starty}, ${value_r}, 0/180*Math.PI,360/180*Math.PI, false);
context.fillStyle = ${fillStyle};
context.fill();
${next}
`;
return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="startX">
<shadow type="math_number">
<field name="NUM">200</field>
</shadow>
</value>
<value name="startY">
<shadow type="math_number">
<field name="NUM">200</field>
</shadow>
</value>
<value name="R">
<shadow type="math_number">
<field name="NUM">8</field>
</shadow>
</value>
<value name="fillStyle">
<shadow type="colour_picker">
<field name="COLOUR">#000000</field>
</shadow>
</value>
</block>`
};
}
Insert cell
Insert cell
function canvasBlocklyArc(Blockly) {
const name = BlocklyCanvasConstants.Arc;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("圆弧");
this.appendValueInput("startX")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X");
this.appendValueInput("startY")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y");
this.appendValueInput("R")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("R");
this.appendValueInput("startAngle")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("起始角");
this.appendValueInput("endAngle")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("结束角");
this.appendValueInput("counterclockwise")
.setCheck("Boolean")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("逆时针");
this.setOutput(true, null);
this.setColour(190);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_startx = Blockly.JavaScript.valueToCode(
block,
'startX',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_starty = Blockly.JavaScript.valueToCode(
block,
'startY',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_r = Blockly.JavaScript.valueToCode(
block,
'R',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_startangle = Blockly.JavaScript.valueToCode(
block,
'startAngle',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_endangle = Blockly.JavaScript.valueToCode(
block,
'endAngle',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_counterclockwise = Blockly.JavaScript.valueToCode(
block,
'counterclockwise',
Blockly.JavaScript.ORDER_NONE
);

let code = ` context.arc(${value_startx},${value_starty},${value_r},${value_startangle}/180*Math.PI,${value_endangle}/180*Math.PI,${value_counterclockwise});
${next}
`;
return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="startAngle">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
<value name="endAngle">
<shadow type="math_number">
<field name="NUM">360</field>
</shadow>
</value>
<value name="startX">
<shadow type="math_number">
<field name="NUM">200</field>
</shadow>
</value>
<value name="startY">
<shadow type="math_number">
<field name="NUM">200</field>
</shadow>
</value>
<value name="R">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="counterclockwise">
<shadow type="logic_boolean">
<field name="BOOL">false</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Triangle`
Insert cell
function canvasTriangle(Blockly) {
const name = BlocklyCanvasConstants.Triangle;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("三角形");
this.appendValueInput("X1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X1");
this.appendValueInput("Y1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y1");
this.appendValueInput("X2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X2");
this.appendValueInput("Y2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y2");
this.appendValueInput("X3")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X3");
this.appendValueInput("Y3")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y3");
this.setOutput(true, null);
this.setColour(210);
this.setTooltip("");
this.setHelpUrl("");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x1 = Blockly.JavaScript.valueToCode(
block,
'X1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y1 = Blockly.JavaScript.valueToCode(
block,
'Y1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x2 = Blockly.JavaScript.valueToCode(
block,
'X2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y2 = Blockly.JavaScript.valueToCode(
block,
'Y2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x3 = Blockly.JavaScript.valueToCode(
block,
'X3',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y3 = Blockly.JavaScript.valueToCode(
block,
'Y3',
Blockly.JavaScript.ORDER_ATOMIC
);

let code = `
context.moveTo(${value_x1}, ${value_y1});
context.lineTo(${value_x2}, ${value_y2});
context.lineTo(${value_x3}, ${value_y3});
context.lineTo(${value_x1}, ${value_y1});
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X1">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="Y1">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="X2">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="Y2">
<shadow type="math_number">
<field name="NUM">300</field>
</shadow>
</value>
<value name="X3">
<shadow type="math_number">
<field name="NUM">300</field>
</shadow>
</value>
<value name="Y3">
<shadow type="math_number">
<field name="NUM">300</field>
</shadow>
</value>
</block>`
};
}
Insert cell
Insert cell
function canvasBezierCurve(Blockly) {
const name = BlocklyCanvasConstants.BezierCurve;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("贝赛尔曲线");
this.appendValueInput("X1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X1");
this.appendValueInput("Y1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y1");
this.appendValueInput("X2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X2");
this.appendValueInput("Y2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y2");
this.appendValueInput("X3")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X3");
this.appendValueInput("Y3")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y3");
this.appendValueInput("X4")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X4");
this.appendValueInput("Y4")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y4");
this.setOutput(true, null);
this.setColour(230);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/bezierCurveTo");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x1 = Blockly.JavaScript.valueToCode(
block,
'X1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y1 = Blockly.JavaScript.valueToCode(
block,
'Y1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x2 = Blockly.JavaScript.valueToCode(
block,
'X2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y2 = Blockly.JavaScript.valueToCode(
block,
'Y2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x3 = Blockly.JavaScript.valueToCode(
block,
'X3',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y3 = Blockly.JavaScript.valueToCode(
block,
'Y3',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x4 = Blockly.JavaScript.valueToCode(
block,
'X4',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y4 = Blockly.JavaScript.valueToCode(
block,
'Y4',
Blockly.JavaScript.ORDER_ATOMIC
);

let code = `
context.moveTo(${value_x1}, ${value_y1});
context.bezierCurveTo(${value_x2}, ${value_y2}, ${value_x3}, ${value_y3}, ${value_x4}, ${value_y4});
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X1">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="Y1">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="X2">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="Y2">
<shadow type="math_number">
<field name="NUM">300</field>
</shadow>
</value>
<value name="X3">
<shadow type="math_number">
<field name="NUM">300</field>
</shadow>
</value>
<value name="Y3">
<shadow type="math_number">
<field name="NUM">300</field>
</shadow>
</value>
<value name="X4">
<shadow type="math_number">
<field name="NUM">300</field>
</shadow>
</value>
<value name="Y4">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### QuadraticCurve`
Insert cell
function canvasQuadraticCurve(Blockly) {
const name = BlocklyCanvasConstants.QuadraticCurve;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("二次方曲线");
this.appendValueInput("X1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X1");
this.appendValueInput("Y1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y1");
this.appendValueInput("X2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X2");
this.appendValueInput("Y2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y2");
this.appendValueInput("X3")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X3");
this.appendValueInput("Y3")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y3");
this.setOutput(true, null);
this.setColour(250);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/quadraticCurveTo");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x1 = Blockly.JavaScript.valueToCode(
block,
'X1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y1 = Blockly.JavaScript.valueToCode(
block,
'Y1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x2 = Blockly.JavaScript.valueToCode(
block,
'X2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y2 = Blockly.JavaScript.valueToCode(
block,
'Y2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x3 = Blockly.JavaScript.valueToCode(
block,
'X3',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y3 = Blockly.JavaScript.valueToCode(
block,
'Y3',
Blockly.JavaScript.ORDER_ATOMIC
);
let code = `
context.moveTo(${value_x1}, ${value_y1});
context.quadraticCurveTo(${value_x2}, ${value_y2}, ${value_x3}, ${value_y3});
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X1">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="Y1">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="X2">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="Y2">
<shadow type="math_number">
<field name="NUM">250</field>
</shadow>
</value>
<value name="X3">
<shadow type="math_number">
<field name="NUM">400</field>
</shadow>
</value>
<value name="Y3">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Ellipse`
Insert cell
function canvasEllipse(Blockly) {
const name = BlocklyCanvasConstants.Ellipse;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("椭圆");
this.appendValueInput("X")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X");
this.appendValueInput("Y")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y");
this.appendValueInput("RX")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("RX");
this.appendValueInput("RY")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("RY");
this.appendValueInput("rotation")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("旋转角");
this.appendValueInput("startAngle")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("起始角");
this.appendValueInput("endAngle")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("结束角");
this.appendDummyInput()
.appendField("逆时针")
.appendField(
new Blockly.FieldDropdown([
["假", "false"],
["真", "true"],
]),
"anticlockwise"
);
this.setInputsInline(false);
this.setOutput(true, null);
this.setColour(220);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/ellipse");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x = Blockly.JavaScript.valueToCode(
block,
'X',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y = Blockly.JavaScript.valueToCode(
block,
'Y',
Blockly.JavaScript.ORDER_ATOMIC
);
let radiusX = Blockly.JavaScript.valueToCode(
block,
'RX',
Blockly.JavaScript.ORDER_ATOMIC
);
let radiusY = Blockly.JavaScript.valueToCode(
block,
'RY',
Blockly.JavaScript.ORDER_ATOMIC
);
let rotation = Blockly.JavaScript.valueToCode(
block,
'rotation',
Blockly.JavaScript.ORDER_ATOMIC
);
let startAngle = Blockly.JavaScript.valueToCode(
block,
'startAngle',
Blockly.JavaScript.ORDER_ATOMIC
);
let endAngle = Blockly.JavaScript.valueToCode(
block,
'endAngle',
Blockly.JavaScript.ORDER_ATOMIC
);
let dropdown_anticlockwise = block.getFieldValue('anticlockwise');

let code = `
context.ellipse(${value_x}, ${value_y}, ${radiusX}, ${radiusY}, Math.PI / ${rotation}, ${startAngle}, ${endAngle} * Math.PI, ${dropdown_anticlockwise});
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="Y">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="RX">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="RY">
<shadow type="math_number">
<field name="NUM">75</field>
</shadow>
</value>
<value name="rotation">
<shadow type="math_number">
<field name="NUM">4</field>
</shadow>
</value>
<value name="startAngle">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
<value name="endAngle">
<shadow type="math_number">
<field name="NUM">2</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Text`
Insert cell
function canvasText(Blockly) {
const name = BlocklyCanvasConstants.Text;
Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("文本");
this.appendValueInput("text")
.setCheck("String")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("文字");
this.appendValueInput("X")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X");
this.appendValueInput("Y")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y");
this.appendValueInput("font")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("字体大小");
this.appendValueInput("fontstyle")
.setCheck("Colour")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("字体颜色")
this.appendDummyInput()
.appendField("字体样式")
.appendField(
new Blockly.FieldDropdown([
["Arial", "Arial"],
["Verdana", "Verdana"],
["serif", "serif"],
["Comic Sans MS", "Comic Sans MS"],
["Times New Roman", "Times New Roman"],
]),
"fontfamily"
);
this.setInputsInline(false);
this.setOutput(true, null);
this.setColour(270);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillText");
}
};
Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let text = Blockly.JavaScript.valueToCode(
block,
'text',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x = Blockly.JavaScript.valueToCode(
block,
'X',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y = Blockly.JavaScript.valueToCode(
block,
'Y',
Blockly.JavaScript.ORDER_ATOMIC
);
let font = Blockly.JavaScript.valueToCode(
block,
'font',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_fontstyle = Blockly.JavaScript.valueToCode(
block,
'fontstyle',
Blockly.JavaScript.ORDER_ATOMIC
);
let dropdown_fontfamily = block.getFieldValue('fontfamily');
let code = `
context.font = "${font}px ${dropdown_fontfamily}";
context.fillText(${text}, ${value_x}, ${value_y});
context.fillStyle = ${value_fontstyle};
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};
return {
kind: "block",
blockxml: `<block type="${name}">
<value name="text">
<shadow type="text_multiline">
<field name="TEXT">Hello World</field>
</shadow>
</value>
<value name="X">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
<value name="Y">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="font">
<shadow type="math_number">
<field name="NUM">30</field>
</shadow>
</value>
<value name="fontstyle">
<shadow type="colour_picker">
<field name="COLOUR">#000000</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Image`
Insert cell
function canvasImage(Blockly) {
const name = BlocklyCanvasConstants.Image;
Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("图像");
this.appendValueInput("image")
.setCheck("String")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("URL");
this.appendValueInput("sx")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("SX");
this.appendValueInput("sy")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("SY");
this.appendValueInput("sWidth")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("SWidth");
this.appendValueInput("sHeight")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("SHeight")
this.appendValueInput("dx")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("DX")
this.appendValueInput("dy")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("DY")
this.appendValueInput("dWidth")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("DWidth")
this.appendValueInput("dHeight")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("DHeight")
this.setInputsInline(false);
this.setOutput(true, null);
this.setColour(275);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage");
}
};
Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let image = Blockly.JavaScript.valueToCode(
block,
'image',
Blockly.JavaScript.ORDER_ATOMIC
);
let sx = Blockly.JavaScript.valueToCode(
block,
'sx',
Blockly.JavaScript.ORDER_ATOMIC
);
let sy = Blockly.JavaScript.valueToCode(
block,
'sy',
Blockly.JavaScript.ORDER_ATOMIC
);
let sWidth = Blockly.JavaScript.valueToCode(
block,
'sWidth',
Blockly.JavaScript.ORDER_ATOMIC
);
let sHeight = Blockly.JavaScript.valueToCode(
block,
'sHeight',
Blockly.JavaScript.ORDER_ATOMIC
);
let dx = Blockly.JavaScript.valueToCode(
block,
'dx',
Blockly.JavaScript.ORDER_ATOMIC
);
let dy = Blockly.JavaScript.valueToCode(
block,
'dy',
Blockly.JavaScript.ORDER_ATOMIC
);
let dWidth = Blockly.JavaScript.valueToCode(
block,
'dWidth',
Blockly.JavaScript.ORDER_ATOMIC
);
let dHeight = Blockly.JavaScript.valueToCode(
block,
'dHeight',
Blockly.JavaScript.ORDER_ATOMIC
);
let code = `
var img = new Image();
img.src = ${image};
img.onload = function(){
context.drawImage(img, ${sx}, ${sy}, ${sWidth}, ${sHeight}, ${dx}, ${dy}, ${dWidth}, ${dHeight});
}
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};
return {
kind: "block",
blockxml: `<block type="${name}">
<value name="image">
<shadow type="text_multiline">
<field name="TEXT">https://mdn.mozillademos.org/files/5397/rhino.jpg</field>
</shadow>
</value>
<value name="sx">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
<value name="sy">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
<value name="sWidth">
<shadow type="math_number">
<field name="NUM">400</field>
</shadow>
</value>
<value name="sHeight">
<shadow type="math_number">
<field name="NUM">500</field>
</shadow>
</value>
<value name="dx">
<shadow type="math_number">
<field name="NUM">50</field>
</shadow>
</value>
<value name="dy">
<shadow type="math_number">
<field name="NUM">30</field>
</shadow>
</value>
<value name="dWidth">
<shadow type="math_number">
<field name="NUM">300</field>
</shadow>
</value>
<value name="dHeight">
<shadow type="math_number">
<field name="NUM">400</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### SetTransform`
Insert cell
function canvasSetTransform(Blockly) {
const name = BlocklyCanvasConstants.SetTransform;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("设置变换");
this.appendValueInput("X1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X1");
this.appendValueInput("X2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X2");
this.appendValueInput("X3")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X3");
this.appendValueInput("X4")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X4");
this.appendValueInput("X5")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X5");
this.appendValueInput("X6")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X6");
this.setOutput(true, null);
this.setColour(290);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setTransform");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x1 = Blockly.JavaScript.valueToCode(
block,
'X1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x2 = Blockly.JavaScript.valueToCode(
block,
'X2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x3 = Blockly.JavaScript.valueToCode(
block,
'X3',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x4 = Blockly.JavaScript.valueToCode(
block,
'X4',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x5 = Blockly.JavaScript.valueToCode(
block,
'X5',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x6 = Blockly.JavaScript.valueToCode(
block,
'X6',
Blockly.JavaScript.ORDER_ATOMIC
);

let code = `
context.setTransform(${value_x1}, ${value_x2}, ${value_x3}, ${value_x4}, ${value_x5}, ${value_x6});
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X1">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="X2">
<shadow type="math_number">
<field name="NUM">0.5</field>
</shadow>
</value>
<value name="X3">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
<value name="X4">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="X5">
<shadow type="math_number">
<field name="NUM">30</field>
</shadow>
</value>
<value name="X6">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Transform`
Insert cell
function canvasTransform(Blockly) {
const name = BlocklyCanvasConstants.Transform;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("变换");
this.appendValueInput("X1")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X1");
this.appendValueInput("X2")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X2");
this.appendValueInput("X3")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X3");
this.appendValueInput("X4")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X4");
this.appendValueInput("X5")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X5");
this.appendValueInput("X6")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X6");
this.setOutput(true, null);
this.setColour(310);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/transform");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x1 = Blockly.JavaScript.valueToCode(
block,
'X1',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x2 = Blockly.JavaScript.valueToCode(
block,
'X2',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x3 = Blockly.JavaScript.valueToCode(
block,
'X3',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x4 = Blockly.JavaScript.valueToCode(
block,
'X4',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x5 = Blockly.JavaScript.valueToCode(
block,
'X5',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_x6 = Blockly.JavaScript.valueToCode(
block,
'X6',
Blockly.JavaScript.ORDER_ATOMIC
);

let code = `
context.transform(${value_x1}, ${value_x2}, ${value_x3}, ${value_x4}, ${value_x5}, ${value_x6});
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X1">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="X2">
<shadow type="math_number">
<field name="NUM">0.5</field>
</shadow>
</value>
<value name="X3">
<shadow type="math_number">
<field name="NUM">0</field>
</shadow>
</value>
<value name="X4">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="X5">
<shadow type="math_number">
<field name="NUM">30</field>
</shadow>
</value>
<value name="X6">
<shadow type="math_number">
<field name="NUM">10</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Translate`
Insert cell
function canvasTranslate(Blockly) {
const name = BlocklyCanvasConstants.Translate;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("平移");
this.appendValueInput("X")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X");
this.appendValueInput("Y")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y");
this.setOutput(true, null);
this.setColour(330);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/translate");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x = Blockly.JavaScript.valueToCode(
block,
'X',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y = Blockly.JavaScript.valueToCode(
block,
'Y',
Blockly.JavaScript.ORDER_ATOMIC
);

let code = `
context.translate(${value_x}, ${value_y});
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X">
<shadow type="math_number">
<field name="NUM">100</field>
</shadow>
</value>
<value name="Y">
<shadow type="math_number">
<field name="NUM">30</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Scale`
Insert cell
function canvasScale(Blockly) {
const name = BlocklyCanvasConstants.Scale;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("缩放");
this.appendValueInput("X")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("X");
this.appendValueInput("Y")
.setCheck("Number")
.setAlign(Blockly.ALIGN_CENTRE)
.appendField("Y");
this.setOutput(true, null);
this.setColour(350);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/scale");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);
let value_x = Blockly.JavaScript.valueToCode(
block,
'X',
Blockly.JavaScript.ORDER_ATOMIC
);
let value_y = Blockly.JavaScript.valueToCode(
block,
'Y',
Blockly.JavaScript.ORDER_ATOMIC
);

let code = `
context.scale(${value_x}, ${value_y});
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
<value name="X">
<shadow type="math_number">
<field name="NUM">-1</field>
</shadow>
</value>
<value name="Y">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>`
};
}
Insert cell
md`### Clock`
Insert cell
function canvasClock(Blockly) {
const name = BlocklyCanvasConstants.Clock;

Blockly.Blocks[name] = {
init: function() {
this.appendValueInput("next")
.setCheck(null)
.appendField("时钟");
this.setOutput(true, null);
this.setColour(360);
this.setTooltip("");
this.setHelpUrl("https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations");
}
};

Blockly.JavaScript[name] = function(block) {
let next = Blockly.JavaScript.valueToCode(
block,
'next',
Blockly.JavaScript.ORDER_NONE
);

let code = `
function clock() {
var now = new Date();
var ctx = document.getElementById('canvas').getContext('2d');
ctx.save();
ctx.clearRect(0, 0, 150, 150);
ctx.translate(75, 75);
ctx.scale(0.4, 0.4);
ctx.rotate(-Math.PI / 2);
ctx.strokeStyle = 'black';
ctx.fillStyle = 'white';
ctx.lineWidth = 8;
ctx.lineCap = 'round';

// Hour marks
ctx.save();
for (var i = 0; i < 12; i++) {
ctx.beginPath();
ctx.rotate(Math.PI / 6);
ctx.moveTo(100, 0);
ctx.lineTo(120, 0);
ctx.stroke();
}
ctx.restore();

// Minute marks
ctx.save();
ctx.lineWidth = 5;
for (i = 0; i < 60; i++) {
if (i % 5!= 0) {
ctx.beginPath();
ctx.moveTo(117, 0);
ctx.lineTo(120, 0);
ctx.stroke();
}
ctx.rotate(Math.PI / 30);
}
ctx.restore();

var sec = now.getSeconds();
var min = now.getMinutes();
var hr = now.getHours();
hr = hr >= 12 ? hr - 12 : hr;

ctx.fillStyle = 'black';

// write Hours
ctx.save();
ctx.rotate(hr * (Math.PI / 6) + (Math.PI / 360) * min + (Math.PI / 21600) *sec);
ctx.lineWidth = 14;
ctx.beginPath();
ctx.moveTo(-20, 0);
ctx.lineTo(80, 0);
ctx.stroke();
ctx.restore();

// write Minutes
ctx.save();
ctx.rotate((Math.PI / 30) * min + (Math.PI / 1800) * sec);
ctx.lineWidth = 10;
ctx.beginPath();
ctx.moveTo(-28, 0);
ctx.lineTo(112, 0);
ctx.stroke();
ctx.restore();

// Write seconds
ctx.save();
ctx.rotate(sec * Math.PI / 30);
ctx.strokeStyle = '#D40000';
ctx.fillStyle = '#D40000';
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(-30, 0);
ctx.lineTo(83, 0);
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, 10, 0, Math.PI * 2, true);
ctx.fill();
ctx.beginPath();
ctx.arc(95, 0, 10, 0, Math.PI * 2, true);
ctx.stroke();
ctx.fillStyle = 'rgba(0, 0, 0, 0)';
ctx.arc(0, 0, 3, 0, Math.PI * 2, true);
ctx.fill();
ctx.restore();

ctx.beginPath();
ctx.lineWidth = 14;
ctx.strokeStyle = '#325FA2';
ctx.arc(0, 0, 142, 0, Math.PI * 2, true);
ctx.stroke();

ctx.restore();

window.requestAnimationFrame(clock);
}

window.requestAnimationFrame(clock);
${next}
`;

return [code, Blockly.JavaScript.ORDER_NONE];
};

return {
kind: "block",
blockxml: `<block type="${name}">
</block>`
};
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more