类型 | 属性 | 方法 | 事件 |
---|---|---|---|
BaseLineWidthPicker | id: string value: number |
blur() | onchange(event: Event) |
BaseColorPicker | id: string value: Color palette: string |
blur() | onchange(event: Event) |
ColorPicker | id: string palette: string value: Color |
blur() | onchange(event: Event) |
在 29 讲的基础上,我们增加了以下能力:
功能 | 请求包 | 返回包 |
---|---|---|
同步变更 | POST /drawings/<DrawingID> /syncContent-Type: application/json { "shapes": [ <ShapeID1> , <ShapeID2> , <ShapeID3> , ...],"changes": [ { "id": <ShapeID> ,<Shape> }, ... ] } |
200 OK |
功能 | 请求包 | 返回包 |
---|---|---|
创建新drawing | POST /drawings | 200 OK Content-Type: application/json { "id": <DrawingID> } |
获得drawing | GET /drawings/<DrawingID> |
200 OK Content-Type: application/json { "shapes": [ { "id": <ShapeID> <Shape> }, ... ] } |
删除drawing | DELETE /drawings/<DrawingID> |
200 OK |
创建新shape | POST /drawings/<DrawingID> /shapesContent-Type: application/json { "id": <ShapeID> ,<Shape> } |
200 OK |
取得shape | GET /drawings/<DrawingID> /shapes/<ShapeID> |
200 OK Content-Type: application/json { <Shape> } |
修改shape | POST /drawings/<DrawingID> /shapes/<ShapeID> Content-Type: application/json { <Shape> } |
200 OK |
修改shape的顺序 | POST /drawings/<DrawingID> /shapes/<ShapeID> Content-Type: application/json { "zorder": <ZorderOperation> } |
200 OK |
删除shape | DELETE /drawings/<DrawingID> /shapes/<ShapeID> |
200 OK |
其中 <Shape>
是这样的:
"path": {
"points": [
{"x": <X>, "y": <Y>},
...
],
"close": <Boolean>,
"style": <ShapeStyle>
}
或:
"line": {
"pt1": {"x": <X>, "y": <Y>},
"pt2": {"x": <X>, "y": <Y>},
"style": <ShapeStyle>
}
或:
"rect": {
"x": <X>,
"y": <Y>,
"width": <Width>,
"height": <Height>,
"style": <ShapeStyle>
}
或:
"ellipse": {
"x": <X>,
"y": <Y>,
"radiusX": <RadiusX>,
"radiusY": <RadiusY>,
"style": <ShapeStyle>
}
其中 <ShapeStyle>
是这样的:
{
"lineWidth": <Width>, // 线宽
"lineColor": <Color>, // 线型颜色
"fillColor": <Color> // 填充色
}
其中 <ZorderOperation>
可能的值为:
- "top": 到最顶
- "bottom": 到最底
- "front": 往前一层
- "back": 往后一层
interface Shape {
onpaint(ctx: CanvasRenderingContext2D): void
bound(): Rect
hitTest(pt: Point): {hitCode: number, hitShape: Shape}
setProp(key: string, val: any): void
move(dx, dy: number): void
}
类型 | View | Controllers |
---|---|---|
QPaintDoc | onpaint(ctx) | addShape(shape) deleteShape(shape) hitTest(pt) |
QLine QRect QEllipse QPath |
onpaint(ctx) | new QLine(pt1, pt2, style) new QRect(rect, style) new QEllipse(x, y, radiusX, radiusY, style) new QPath(points, close, style) bound() hitTest(pt) setProp(key, val) move(dx, dy) |
QShapeStyle | new QShapeStyle( lineWidth, lineColor, fillColor ) |
setProp(key, val) clone() |
interface Controller {
stop(): void
onpaint(ctx: CanvasRenderingContext2D): void
}
类型 | Model | View | Controllers |
---|---|---|---|
数据 | doc: QPaintDoc | style: QShapeStyle drawing: DOMElement |
controllers: map[string]Controller |
方法 | - | invalidateRect(rect) | get currentKey() get selection() set selection(shape) getMousePos(event) registerController(name, ctrl) invokeController(name) stopController() fireControllerReset() |
事件 | - | onpaint(ctx) | onmousedown(event) onmousemove(event) onmouseup(event) ondblclick(event) onkeydown(event) onSelectionChanged(old) onControllerReset() |
- Menu, PropSelectors, MousePosTracker: accel/menu.js
- ShapeSelector: accel/select.js
- Create Path: creator/path.js
- Create FreePath: creator/freepath.js
- Create Line, Rect, Ellipse, Circle: creator/rect.js
类型 | Event | Model | View |
---|---|---|---|
Menu | onControllerReset() | - | controllers: map[string]Controller get currentKey() invokeController(name) |
PropSelectors | onSelectionChanged(old) | shape.style shape.setProp(key, val) style.clone() |
style: QShapeStyle get selection() invalidateRect(rect) |
MousePosTracker | onmousemove | - | getMousePos(event) |
QShapeSelector | onmousedown(event) onmousemove(event) onmouseup(event) onkeydown(event) onpaint(ctx) |
doc.deleteShape(shape) doc.hitTest(pt) shape.move(dx, dy) shape.bound() |
get selection() set selection(shape) getMousePos(event) invalidateRect(rect) registerController(name, ctrl) |
QPathCreator | onmousedown(event) onmousemove(event) onmouseup(event) ondblclick(event) onkeydown(event) onpaint(ctx) |
new QPath(points, close, style) doc.addShape(shape) |
getMousePos(event) invalidateRect(rect) registerController(name, ctrl) fireControllerReset() |
QFreePathCreator | onmousedown(event) onmousemove(event) onmouseup(event) onkeydown(event) onpaint(ctx) |
new QPath(points, close, style) doc.addShape(shape) |
getMousePos(event) invalidateRect(rect) registerController(name, ctrl) fireControllerReset() |
QRectCreator | onmousedown(event) onmousemove(event) onmouseup(event) onkeydown(event) onpaint(ctx) |
new QLine(pt1, pt2, style) new QRect(rect, style) new QEllipse(x, y, radiusX, radiusY, style) doc.addShape(shape) |
getMousePos(event) invalidateRect(rect) registerController(name, ctrl) fireControllerReset() |
类型 | View | Controllers | 修改说明 |
---|---|---|---|
QPaintDoc | - | deleteShape(shape) hitTest(pt) |
- 增加 hitTest (确定鼠标点中哪个图形)、deleteShape (删除某个图形),都用于 QShapeSelector |
QLine QRect QEllipse QPath |
- | new QLine(pt1, pt2, style) new QRect(rect, style) new QEllipse(x, y, radiusX, radiusY, style) new QPath(points, close, style) bound() hitTest(pt) setProp(key, val) move(dx, dy) |
- 构造函数 style 参数由 QLineStyle 改为 QShapeStyle - bound (求图形的外接矩形)、hitTest 用于选择图形 - setProp (修改图形样式的某个属性) - move (移动图形) |
QShapeStyle | new QShapeStyle( lineWidth, lineColor, fillColor ) |
setProp(key, val) clone() |
- QLineStyle 改名为 QShapeStyle - 属性 width、color 改名为 lineWidth、lineColor - 增加属性 fillColor (图形的填充色) - 增加 setProp、clone (克隆图形样式) |
类型 | Model | View | Controllers | 修改说明 |
---|---|---|---|---|
数据 | - | style: QShapeStyle | - | - 属性 properties 改名为 style |
方法 | - | - | get selection() set selection(shape) fireControllerReset() |
- 删除了 get lineStyle(),和 properties 统一为 style - 增加了 selection 读写 - fireControllerReset,用于让创建图形的 Controller 完成或放弃图形创建时发出 onControllerReset 事件 |
事件 | - | - | onSelectionChanged(old) onControllerReset() |
- onSelectionChanged 在被选择的图形改变时发出 - onControllerReset (见 fireControllerReset 的说明) |
类型 | Event | Model | View | 修改说明 |
---|---|---|---|---|
Menu | onControllerReset() | - | - | - 引入了 v2 版本的切换 Controller 的范式,更接近现代的交互范式 |
PropSelectors | onSelectionChanged(old) | shape.style shape.setProp(key, val) style.clone() |
style: QShapeStyle get selection() invalidateRect(rect) |
- 这个 Controller 要比上一版本的复杂很多:之前只是修改 view 的 properties (现在是 style) 属性,以便于创建图形时引用。现在是改变它时还会作用于 selection (被选中的图形),改变它的样式;而且,在 selection 改变时,会自动更新界面以反映被选图形的样式 |
MousePosTracker | - | - | - | - 无变化 |
QShapeSelector | onmousedown(event) onmousemove(event) onmouseup(event) onkeydown(event) onpaint(ctx) |
doc.deleteShape(shape) doc.hitTest(pt) shape.move(dx, dy) shape.bound() |
get selection() set selection(shape) getMousePos(event) invalidateRect(rect) registerController(name, ctrl) |
- 完全新增的 Controller |
QPathCreator | - | new QPath(points, close, style) | fireControllerReset() | - QPath 的 style 参数从 QLineStyle 变为 QShapeStyle - 完成或放弃图形创建时发出 onControllerReset 事件 |
QFreePathCreator | - | new QPath(points, close, style) | fireControllerReset() | - 同上 |
QRectCreator | - | new QLine(pt1, pt2, style) new QRect(rect, style) new QEllipse(x, y, radiusX, radiusY, style) |
fireControllerReset() | - 同上 |
interface Shape {
onpaint(ctx: CanvasRenderingContext2D): void
}
类型 | View | Controllers |
---|---|---|
QPaintDoc | onpaint(ctx) | addShape(shape) |
QLine QRect QEllipse QPath |
onpaint(ctx) | new QLine(pt1, pt2, style) new QRect(rect, style) new QEllipse(x, y, radiusX, radiusY, style) new QPath(points, close, style) |
QLineStyle | - | new QLineStyle(width, color) |
interface Controller {
stop(): void
onpaint(ctx: CanvasRenderingContext2D): void
}
类型 | Model | View | Controllers |
---|---|---|---|
数据 | doc: QPaintDoc | properties: { lineWidth: number lineColor: string } drawing: DOMElement |
controllers: map[string]Controller |
方法 | - | invalidateRect(rect) | get currentKey() get lineStyle() getMousePos(event) registerController(name, ctrl) invokeController(name) stopController() |
事件 | - | onpaint(ctx) | onmousedown(event) onmousemove(event) onmouseup(event) ondblclick(event) onkeydown(event) |
- Menu, PropSelectors, MousePosTracker: accel/menu.js
- Create Path: creator/path.js
- Create FreePath: creator/freepath.js
- Create Line, Rect, Ellipse, Circle: creator/rect.js
类型 | Event | Model | View |
---|---|---|---|
Menu | - | - | controllers: map[string]Controller get currentKey() invokeController(name) |
PropSelectors | - | - | properties: { lineWidth: number lineColor: string } |
MousePosTracker | onmousemove | - | getMousePos(event) |
QPathCreator | onmousedown(event) onmousemove(event) onmouseup(event) ondblclick(event) onkeydown(event) onpaint(ctx) |
new QPath(points, close, style) doc.addShape(shape) |
getMousePos(event) invalidateRect(rect) registerController(name, ctrl) |
QFreePathCreator | onmousedown(event) onmousemove(event) onmouseup(event) onkeydown(event) onpaint(ctx) |
new QPath(points, close, style) doc.addShape(shape) |
getMousePos(event) invalidateRect(rect) registerController(name, ctrl) |
QRectCreator | onmousedown(event) onmousemove(event) onmouseup(event) onkeydown(event) onpaint(ctx) |
new QLine(pt1, pt2, style) new QRect(rect, style) new QEllipse(x, y, radiusX, radiusY, style) doc.addShape(shape) |
getMousePos(event) invalidateRect(rect) registerController(name, ctrl) |