# project-1
**Repository Path**: lijb55/project-1
## Basic Information
- **Project Name**: project-1
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 9
- **Created**: 2022-06-16
- **Last Updated**: 2022-06-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 在线 SVG 编辑器
##### 主要实现内容,在控制面板中添加了撤销,返回,复制,粘贴选项。
- undo&redo
- 撤销和返回功能,选中左边面板的undo键,随后点击任意地方,画板将返回上一次操作执行前的状态,选中redo键,取消撤销。当undo状态撤销操作后,接上后续操作,则无法再redo:
- 实现方式:
(1)维护一个全局变量列表保存每次更新前的状态,在ResizeController的drag函数,append和remove函数中,每一次变换前(增删改)保存操作对象和操作方式。
```python
def drag(self, x1, y1, x2, y2, drag_event):
if drag_event is not None:
c, action = drag_event
c.drag(action, x1, y1, x2, y2)
return drag_event
for c in self.controller_panel.svg.children[::-1]:
# 在变换前存储状态,用于撤销操作
s = {c.elt:c.getAttribute()}
move_stack.push('state')
state_stack.push(s)
action = c.action(x1,y1)
if action!='auto':
c.drag(action, x1, y1, x2, y2)
return [c, action]
```
(2)对于撤销返回,因为之前记录的是最后一次操作之前的内容,所以最新的内容是没有记录,需要额外一个变量记录当前状态并加入列表中。通过一个current_state指针找到需要变到哪个状态。
(3)当撤销后,接着create或resize或remove操作时,此时redo将不可用,则将列表中当前状态后的所有状态删除。
```python
while self.current_state < self.len:
self.items.pop()
self.len = self.len-1
```
- copy&paste
- 复制粘贴功能,选中控制面板的复制,点击想要复制的对象,则将记录该对象的类和属性;选中控制面板的粘贴,点击任意位置,在原对象附近生成新的复制对象:

- 实现方式:
(1)保存一个全局变量记录鼠标选中的对象,记录其类型和参数,再粘贴时将内容的类和属性保存下来,然后新建类和加入svg子图中。
```python
class CopyController(Controller):
def __init__(self):
super(CopyController,self).__init__()
shape = _make_svg('path', {'d':"M6 6V2c0-1.1.9-2 2-2h10a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-4v4a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V8c0-1.1.9-2 2-2h4zm2 0h4a2 2 0 0 1 2 2v4h4V2H8v4zM2 8v10h10V8H2z", 'fill':'#486e93', 'stroke':'black', 'stroke-width':1, 'transform':"translate(6,6)"})
self.svg.appendChild(shape)
def click(self, x, y):
for c in self.controller_panel.svg.children[::-1]:
action = c.action(x,y)
if action!='auto':
global copy
copy = {c.elt:c}
break
def move(self, x, y):
for c in self.controller_panel.svg.children[::-1]:
action = c.action(x,y)
if action!='auto':
self.controller_panel.svg.div.style.cursor = "pointer"
break
else:
self.controller_panel.svg.div.style.cursor = 'auto'
class PasteController(Controller):
def __init__(self):
super(PasteController,self).__init__()
shape = _make_svg('path', {'d':"M10.5 20H2a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2h1V3l2.03-.4a3 3 0 0 1 5.94 0L13 3v1h1a2 2 0 0 1 2 2v1h-2V6h-1v1H3V6H2v12h5v2h3.5zM8 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm2 4h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-8a2 2 0 0 1-2-2v-8c0-1.1.9-2 2-2zm0 2v8h8v-8h-8z", 'fill':'#486e93', 'stroke':'black', 'stroke-width':1, 'transform':"translate(6,6)"})
self.svg.appendChild(shape)
def click(self, x, y):
for item in copy.items():
print("create")
print(item[1])
if item[1].getName() == 'Rect':
p = []
for i in item[1].getAttribute().items():
p.append(i[1])
x = p[0]
y = p[1]
width = p[2]
height = p[3]
rect = Rect(x-50, y-50, width, height)
self.controller_panel.svg.append(rect)
elif item[1].getName() == 'Eclipse':
p = []
for i in item[1].getAttribute().items():
p.append(i[1])
x = p[0]
y = p[1]
width = p[2]
height = p[3]
eclipse = Eclipse(x-50, y-50, width, height)
self.controller_panel.svg.append(eclipse)
else: print("wrong class")
```