新闻详情

新闻详情

首页 / 资讯中心 / 详情

折叠屏展开后不该丢掉编辑进度:海报画布如何保持连续

发布时间:2026/9/27 22:00:20来源:尧图网络
折叠屏展开后不该丢掉编辑进度:海报画布如何保持连续
编辑海报时临时把折叠屏展开画布面积变大了但刚才选中的元素、缩放比例和撤销记录不能跟着消失。折叠屏展开后不该丢掉编辑进度海报画布如何保持连续需要的不只是首屏效果还要补上画布元素、选中标识、坐标变换和撤销快照。把画布状态从具体页面布局中抽离让折叠态、展开态和宽屏态读取同一份编辑数据。这次按【确定画布坐标系 → 建立元素模型 → 实现选中与移动 → 加入缩放和撤销 → 最后处理形态切换】逐层推进先让关键动作跑通再安排折叠态保留画布与主操作展开后增加图层栏和属性面板。展开屏幕前先固定画布坐标窗口尺寸变化时重新创建页面导致选中元素回到第一项甚至把编辑历史清空。因此先把画布元素、选中标识、坐标变换和撤销快照写成独立模型页面只订阅结果。exportinterfaceCanvasPoint{x:numbery:number}exportinterfaceCanvasElement{id:stringname:stringx:numbery:numberscale:numberopacity:numberselected:boolean}interfaceCanvasSnapshot{elements:CanvasElement[]selectedId:string}exportclassFeatureController{privateelements:CanvasElement[][{id:hero,name:折叠海报画布主视觉,x:120,y:88,scale:1,opacity:1,selected:true},{id:copy,name:标题文本,x:156,y:246,scale:1,opacity:1,selected:false},{id:light,name:氛围光层,x:410,y:120,scale:1.2,opacity:0.42,selected:false}]privatehistory:CanvasSnapshot[][]privateselectedId:stringhero这些字段不引用具体组件折叠屏和平板只需选择自己的呈现方式。一次拖动怎样进入撤销栈实现选中与移动从一个明确命令开始。命令带上目标和输入控制器完成判断后再提交修改。组件把意图交给控制器真正的数据修改只发生在这里。getElements():CanvasElement[]{returnthis.elements}select(id:string):boolean{constexists:booleanthis.elements.some((item:CanvasElement)item.idid)if(!exists){returnfalse}this.selectedIdidthis.elementsthis.elements.map((item:CanvasElement)({id:item.id,name:item.name,x:item.x,y:item.y,scale:item.scale,opacity:item.opacity,selected:item.idid}asCanvasElement))returntrue}moveSelected(point:CanvasPoint):boolean{constindex:numberthis.elements.findIndex((item:CanvasElement)item.idthis.selectedId)if(index0||point.x0||point.y0){returnfalse}this.pushSnapshot()constcurrent:CanvasElementthis.elements[index]this.elements[index]{id:current.id,name:current.name,x:point.x,y:point.y,scale:current.scale,opacity:current.opacity,selected:current.selected}returntrue}updateScale(delta:number):number{constindex:numberthis.elements.findIndex((item:CanvasElement)item.idthis.selectedId)if(index0){这样处理后窗口尺寸变化时重新创建页面导致选中元素回到第一项甚至把编辑历史清空会在写入前被截住。折叠与展开不是两份页面折叠态保留画布与主操作展开后增加图层栏和属性面板。这套排列首先服务折叠屏和平板的观看距离与操作范围。首屏把实现选中与移动对应的结果放在视觉中心次要参数退到边缘区域。import{FeatureController}from../features/FeatureControllerinterfaceFeatureItem{id:numbertitle:stringdetail:string}EntryComponentstruct Index{privatefeatureController:FeatureControllernewFeatureController()StateselectedId:number1Statemessage:string展开屏幕后继续编辑同一个元素Statewide:booleanfalseStatezoomPercent:number92StateshowGrid:booleantrueStateundoCount:number0privateitems:FeatureItem[][{id:1,title:主标题,detail:可交互能力 1},{id:2,title:渐变背景,detail:可交互能力 2},{id:3,title:行动按钮,detail:可交互能力 3}]privateselected():FeatureItem{returnthis.items.find((item:FeatureItem)item.idthis.selectedId)??this.items[0]}privateselectLayer(id:number):void{this.selectedIdidthis.message正在编辑${this.selected().title}}privatechangeZoom(delta:number):void{this.zoomPercentMath.max(60,Math.min(130,this.zoomPercentdelta))this.undoCountthis.message缩放${this.zoomPercent}% · 可撤销${this.undoCount}步}privateundo():void{if(this.undoCount0){this.message没有可撤销操作;return}this.undoCount--this.zoomPercentMath.max(60,this.zoomPercent-4)this.message已撤销剩余${this.undoCount}步}build(){Row({space:14}){Column({space:12}){Text(__TITLE__).fontSize(27).fontWeight(FontWeight.Bold).fontColor(Color.White)Text(this.message).fontSize(12).fontColor(#E7E9FF)List({space:8}){ForEach(this.items,(item:FeatureItem){ListItem(){Row({space:9}){Circle({width:9,height:9}).fill(this.selectedIditem.id?#FFFFFF:#80FFFFFF);Text(item.title).fontSize(15).fontColor(Color.White).layoutWeight(1)}.padding(12).borderRadius(13).backgroundColor(this.selectedIditem.id?#36FFFFFF:#18FFFFFF).onClick(()this.selectLayer(item.id))}},(item:FeatureItem)item.id.toString())}.layoutWeight(1)Row({space:8}){Button(撤销).onClick(()this.undo());Button(this.showGrid?关闭网格:显示网格).onClick((){this.showGrid!this.showGrid})}}.width(this.wide?31%:38%).height(100%).padding(18).borderRadius(24).backgroundColor(__ACCENT__)Column({space:14}){Row(){Text(画布).fontSize(18).fontWeight(FontWeight.Bold);Blank();Text(${this.zoomPercent}%).fontColor(__ACCENT__)}.width(100%)Stack(){Rect().width(${this.zoomPercent}%).height(${Math.min(82,this.zoomPercent*0.65)}%).radius(24).fill(#EEF0F8)Column({space:10}){Text(this.selected().title).fontSize(27).fontWeight(FontWeight.Bold).fontColor(__ACCENT__);Text(选中元素保持稳定窗口变化后继续编辑).fontSize(12).fontColor(#667085)}.padding(24)}.layoutWeight(1).width(100%).backgroundColor(this.showGrid?#F7F8FC:Color.White).borderRadius(24)Row({space:10}){Button(缩小).onClick(()this.changeZoom(-4));Button(放大).backgroundColor(__ACCENT__).onClick(()this.changeZoom(4))}}.layoutWeight(1).height(100%).padding(18).borderRadius(24).backgroundColor(Color.White)}.width(100%).height(100%).padding(18).backgroundColor(#F2F4F8).onAreaChange((oldArea:Area,newArea:Area){this.wideNumber(newArea.width)760})Index.ets在这里读取控制器结果并组织折叠态保留画布与主操作展开后增加图层栏和属性面板。计算仍留在功能层因此更换设备形态只需调整区域组合。旋转之后找回正在编辑的元素加入缩放和撤销结束后仍可能收到旧事件下面的代码先判断阶段再决定保留或回退。return1}this.pushSnapshot()constcurrent:CanvasElementthis.elements[index]constnext:numberMath.max(0.4,Math.min(2.4,current.scaledelta))this.elements[index]{id:current.id,name:current.name,x:current.x,y:current.y,scale:next,opacity:current.opacity,selected:current.selected}returnnext}undo():boolean{constsnapshot:CanvasSnapshot|undefinedthis.history.pop()if(!snapshot){returnfalse}this.selectedIdsnapshot.selectedIdthis.elementssnapshot.elements.map((item:CanvasElement)({id:item.id,name:item.name,x:item.x,y:item.y,scale:item.scale,opacity:item.opacity,selected:item.selected}asCanvasElement))returntrue}privatepushSnapshot():void{this.history.push({selectedId:this.selectedId,elements:this.elements.map((item:CanvasElement)({id:item.id,name:item.name,x:item.x,y:item.y,scale:item.scale,opacity:item.opacity,selected:item.selected}asCanvasElement))})if(this.history.length30){this.history.shift()}}}失败结果保留最近一次有效状态并给最后处理形态切换留下重新进入的入口。FoldCanvas的文件落点下面是FoldCanvas当前使用的目录。pages负责折叠态保留画布与主操作展开后增加图层栏和属性面板features保存本文展示的业务链路。FoldCanvas/ ├─ entry/src/main/ets/ │ ├─ pages/Index.ets # 首屏与响应式布局 │ ├─ features/FeatureController.ets # 模型、动作和边界 │ ├─ entryability/EntryAbility.ets # 页面入口与生命周期 │ └─ adapters/ # 真机能力或数据源接口 ├─ entry/src/main/resources/ # 颜色、文字和媒体资源 └─ build-profile.json5 # 工程构建配置Index.ets只组合界面FeatureController.ets处理画布元素、选中标识、坐标变换和撤销快照。如果后面接入真实设备或网络服务只需增加适配器并把结果转换成控制器认识的状态。到这里确定画布坐标系与最后处理形态切换已经接到同一份状态上界面变化不会切断编辑过程。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

二维码在企业系统里怎么用?资产标签、产品页和客户入口 2026/9/27 22:48:29

二维码在企业系统里怎么用?资产标签、产品页和客户入口

二维码在企业系统里很常见:贴在设备上,扫一下报修;贴在产品包装上,扫一下看说明书;放在展会物料上,扫一下打开产品页;放在客户服务卡上,扫一下提交售后单。 但二维码不是“把 URL 生…

阅读更多 →
干货:插件 2026/9/27 22:48:29

干货:插件

插件 策略模式:TEMPLATE_ID/PRIORITY/recognizes/parse 四要素 不写进 if-else,写进文件 加一种新的 PDF 格式,最省事的写法是往解析函数里塞 if 是格式A: ... elif 是格式B: ...。但格式一多,核心代码就成了一滩浆糊&#xff0c…

阅读更多 →
235、【AI】【模型部署】基座模型研究:交叉熵 2026/9/27 22:48:29

235、【AI】【模型部署】基座模型研究:交叉熵

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除 标题 235、【AI】【模型部署】基座模型研究&a…

阅读更多 →
Kimi    LeetCode 114.二叉树展开为链表 Kotlin实现 2026/9/27 22:48:22

Kimi LeetCode 114.二叉树展开为链表 Kotlin实现

LeetCode 114. 二叉树展开为链表 — Kotlin 实现 题目要求 将二叉树原地展开为单链表,顺序为先序遍历顺序,用 right 指针充当链表的 next。 思路一:迭代(推荐)O(1)O(1)O(1) 额外空间 对当前节点,若存在左子…

阅读更多 →
简历技术栈全面复习——EtherCAT / IgH Master / CiA402 2026/9/27 22:48:22

简历技术栈全面复习——EtherCAT / IgH Master / CiA402

EtherCAT → IgH Master → CiA402 → CSP。⑥ EtherCAT:机器人电机控制的通信骨架先看整体:你的控制程序↓EtherCAT Master↓PDO↓ EtherCAT Slave↓电机驱动器↓电机如果使用 IgH:机器人控制程序↓ IgH EtherCAT Master↓ EtherCAT↓ Drive…

阅读更多 →
PLC编程必学!S7-1200定时器指令用法,一篇讲透TP/TON/TOF/TONR 2026/9/27 22:48:22

PLC编程必学!S7-1200定时器指令用法,一篇讲透TP/TON/TOF/TONR

做工控PLC编程,延时启动、定时停机、脉冲触发、设备累计计时这些功能,90%都要靠定时器实现。可以说,定时器是西门子S7-1200 PLC编程的核心指令,也是新手入门必须吃透的基础内容。很多刚接触S7-1200的朋友,总是分不清TP…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉