• 关于

    自动渲染

    的搜索结果

问题

阿里云渲染云计算基本介绍

christina 2019-12-01 20:01:47 19953 浏览量 回答数 11

问题

试用云渲染后的一些感受和建议

colaido 2019-12-01 20:03:44 19446 浏览量 回答数 10

回答

画布和SVG都允许您在浏览器中创建图形,但是它们在根本上是不同的。 帆布 描述: 通过Javascript来绘制2D图形。是逐行进行渲染的。其位置发生改变,会重新进行绘制。 SVG 描述: 一种使用XML描述的2D图形的语言SVG基于XML意味着,SVG DOM中的每个元素都是可用的,可以为某个元素附加Javascript事件处理器。在SVG中,每个被布置的图形均如果SVG对象的属性发生变化,那么浏览器能够自动重现图形。 比较 帆布 依赖分辨率 不支持事件处理器 弱的文本渲染能力 能够以.png或.jpg格式保存结果图像 最适合图像密集型的游戏,其中的许多对象会被重复重绘 SVG 不依赖分辨率 支持事件处理器 最适合带有大型渲染区域的应用程序(某些谷歌地图) 复杂度高会减慢渲染速度(任何过度使用DOM的应用都不快) 不适合游戏应用

茶什i 2019-12-02 03:16:13 0 浏览量 回答数 0

回答

静态是真正的html文件来渲染的,伪静态是应用程序根据请求自动生成的页面

han1396735592 2019-12-02 01:35:04 0 浏览量 回答数 0

回答

使用流程 云渲染管理系统(Render Manager 简称渲管)是一个开源的 web 应用,可以帮助用户轻松搭建阿里云上的私有渲染系统,直接调用海量计算资源,一键管控集群规模,在加速渲染任务的同时省去自建集群的烦恼。 渲管首页渲管建立在阿里云 BatchCompute 、OSS 和 ECS 的三个云产品基础之上的。详细介绍请参考官网,在使用渲管前,请确保已开通此三产品。 BatchCompute 是阿里云上的批量计算服务,可以帮助用户进行大规模并行计算。 OSS 是阿里云上的对象存储服务,可以存储海量数据。 ECS 是阿里云上的云服务器,极易运维和操作,可以方便的制作系统镜像。 渲管与这三个云产品的关系如下图rm_c 使用流程 A) 制作计算节点镜像 根据所要使用的区域,创建 ECS 按量云服务器,在云服务器中安装所需的渲染软件;保存为自定义镜像,并将镜像共享给账号1190847048572539,详见计算节点 镜像制作 章节。 B) 上传数据到OSS 将渲染所需要的数据上传到对应区域的OSS,并保持上传前的目录结构。 C) 启动渲管 在 ECS 控制台创建实例(短期使用,选择按量即可),镜像选择镜像市场中的rendermanager(也可以使用渲管安装包进行部署,详见 操作手册 部署章节)。 D) 配置渲管 登录渲管页面 https://ip/rm/login, 配置完基本信息后(AccessKeys 和 OSS bucket),在镜像管理页中添加上面制作的计算节点镜像 ID,并对该计算节点镜像配置渲染命令行。 E) 创建项目 在渲管的项目管理页面创建项目,指定 OSS 的数据映射规则(也称 OSS 挂载,在计算节点启动的时候,OSS 上的数据会被挂载到节点的本地路径),选择计算节点镜像 ID,OSS 的输出路径(用于保存渲染结果),计算节点中的临时输出路径。 F) 集群的创建和管理 在集群管理页面可以按需创建集群,指定计算节点使用的镜像 ID,节点类型和节点数量等信息。 G) 提交渲染作业 在项目页里提交渲染作业,要指定目的集群、渲染的帧范围以及节点数量等信息。提交完作业后,可实时查看渲染日志以及节点 CPU 使用率等信息。 BatchCompute 提供了测试用的计算节点镜像(windows server 2008,ID:m-wz9du0xaa1pag4ylwzsu),它预装了 blender 渲染软件。使用 blender 制作一个小场景的 演示视频 已上传 OSS(测试时,需下载并上传到您的 OSS bucket)。 实际生产时,请根据需求制作合适的计算节点镜像。 准备工作 注册阿里云账号并开通 OSS、ECS 和 BatchCompute 服务。 创建AccessKey。账号信息->AccessKeys->创建 Access Key,记录 Access Key 信息。p0 渲染示例 A) 创建 OSS bucket阿里云官网->管理控制台->对象存储 OSS->创建 bucket(例如,名字为 renderbucket),地域选择深圳(华南1),读写权限为私有。p1p2p3p4 获取blender场景并上传到您的 OSS bucket 在浏览器输入 http://openrm.oss-cn-qingdao.aliyuncs.com/blender/monkey/cube.blend 。 下载示例场景文件(BatchCompute 提供的测试场景),在 OSS 控制台创建目录结构blender/monkey,然后在该目录下上传文件,文件路径为oss://renderbucket/blender/monkey/cube.blend。 启动rendermanager A) 阿里云官网->管理控制台->云服务器 ECS->创建实例 选择按量付费,然后在镜像市场应用开发分类中搜索 rendermanager 镜像,使用 rendermanager 镜像并按下图配置购买,可适当提高带宽。 使用按量付费要求用户账户至少有 100 块金额,对于地域没有要求,看 ECS 实际售卖库存情况而定。 p8p9p001p10 B) 购买后,点击进入管理控制台,在实例列表中可看到刚才启动的云主机(创建会有延迟,请刷新几次)。p11p12 登入渲管页面 在本地浏览器输入 https://ecs_instance_ip/rm/login,ecs_instance_ip 为 ECS 实例的公网 IP(由于使用了 https,请在浏览器页面授权信任)。初始账号密码为: rm_admin rm_admin@123 生产系统,请一定更改账号和密码。 配置渲管 A) 登录后,点击右上角的配置可进入配置页面,填入 SECURITY_ID,SECURITY_KEY, OSS_BUCEKET 三个字段的值,SECURITY_ID 和 SECURITY_KEY 即上面准备工作中获取的 AccessKey 信息。p14 B) 设置 OSS_HOST 为 oss-cn-shenzhen.aliyuncs.com;REGION 的选择主要和计算节点的镜像归属有关,必须和计算节点镜像归属 REGION 保持一致;本例采用的官方计算节点镜像(该镜像部署在深圳 REGION)所以此处设置在深圳 REGION 。 p003 C) 设置 BATCHCOMPUTE_REGION 为 cn-shenzhen;设置深圳 REGION 原因同上。 p004 D) 点击保存。 添加计算节点镜像 镜像管理->添加计算节点镜像,ECS 镜像 ID:m-wz9du0xaa1pag4ylwzsu(BatchCompute 提供的公用计算节点镜像,实际生产,需要用户制作所需要的计算节点镜像,具体制作流程请参考 操作手册)。p15p16 配置渲染软件信息 A) 镜像管理->软件配置。p17 B) 添加软件。p18 C) 选择 blender 模板并确定,执行 render_cmd 渲染命令。p19 创建项目 A) 项目管理->新建项目。p20B) 填入需要映射的 OSS 路径数量(本例只映射一个OSS路径),并点击确认。p21C) 填入项目名称: blender_test。D) 镜像选择上面创建的镜像。E) OSS 映射中的选择/输入路径为 /renderbucket/blender/。F) OSS 映射的目的地为盘符 G: (本例中使用的镜像系统为 Windows2008 server)。G) OSS 输出目录填写为 /renderbucket/rm_test/output/。H) 虚拟机中的输出目录填写为 C:\render_output\,该路径用于渲染节点中临时存放渲染结果,并且该目录里的渲染结果会被传输到 OSS 上输出目录里。I) 确定提交。p22 提交渲染任务 A) 项目管理->提交渲染。p23 B) 选择场景所在的 OSS 路径前缀。p24 C) 选择项目根目录, 直到场景文件cube.blend,选中 monkey 文件夹;可以看到页面下部出现场景选择,勾选场景,选择渲染软件,填入渲染起止帧 1~5,并点击提交渲染按钮。p25 D) 选择渲染中的任务,可查看刚才提交的作业。p26 查看渲染日志 A) 点击任务名称并点击节点列表。p27 B) 点击想查看的节点,可以看到渲染器和渲管 worker 的各种日志、标准输出以及标准出错信息(计算节点运行起来后才能看到日志信息)。p28p29p30 查看渲染结果 A) 等待作业结束后,在已结束的任务中可以可以看到任务状态为 Finished。p31 B) 点击任务名称,可以查看 OSS 上的输出路径。p32 C) 在 OSS 控制台上查看对应输出路径,获取地址后点击获取 URL 并复制。p33 D) 在浏览器粘贴 URL 可以直接查看图片。p34 E) 恭喜您已跑通云上的 Blender 渲染测试。 渲管系统结构 A) 渲管与各云产品的详细关系 渲管与各云产品的依赖如下图所示。rm_c B) 渲管系统内部结构 p0渲管系统由如下 3 部分组成: render manager: 基于 flask 框架开发web 应用,主要负责和用户进行人机交互,接收用户请求。 render master:后台背景进程,根据人机交互的结果进行作业提交以调度。 本地数据库:主要存放用户提交的渲管请求,待渲管任务结束后自动删除该信息。 2. 渲管的部署 在阿里云云市场有已安装了渲管的 ECS 镜像免费售卖,在启动 ECS 实例时,将镜像指定为镜像市场中的 rendermanager,启动即可使用。 A) 获取渲管镜像 官方渲管镜像:RenderManager 镜像,创建 ECS 实例时,选择镜像市场,直接搜索以上关键字即可获取。自定义渲管镜像:基础镜像建议采用 Ubuntu 14.04 64 位,按照以下步骤安装渲管系统。 安装 flask sudo apt-get install python-flask -y 安装 uwsgi sudo apt-get install uwsgi uwsgi-plugin-python -y 安装 nginx sudo apt-get install nginx –y 修改 nginx 配置,在 http 模块里添加新的 server server { listen 1314; #listen port server_name localchost; location / { include uwsgi_params; uwsgi_pass 0.0.0.0:8818;#this must be same app_config.xml } } vi /etc/nginx/nginx.conf 启动 nginx 或重启 nginx 获取最新版渲管 wget http://openrm.oss-cn-qingdao.aliyuncs.com/render_manager_release/latest/rm.tar.gz 解压 tar –xf rm.tar.gz x.x.x 为版本号 cd rm-x.x.x 指定安装目录部署 python deploy.py /root/rm_install/ 启动 cd /root/rm_install/rm_install_s && python rm_cmd.py start 登陆渲管 http://installed_machine_ip:1314/rm/login 初始账号: rm_admin 密码: rm_admin@123 若监听在公网,建议采用https B) 开通 ECS 实例 请指定某 ECS 实例部署渲管系统,配置参数,请参考创建 Linux 实例 公网 IP 地址选择分配。 镜像市场: RenderManager 或者自定义镜像 设置密码 3. 渲管系统升级 p43页面右上角的版本信息中可以查看是否有可升级的新版本,第一次使用渲管前,建议升级到最新版本后再使用渲管(每次只能升级到下一版本,所以升级后请查看是否已是最新版本)。 渲管系统配置 p44配置页面里有渲管系统的各种系统设置。第一次使用渲管时,必须设置SECURITY_ID,SECURITY_KEY,OSS_BUCKET 三个值,不然渲管无法使用。 SECURITY_ID 和 SECURITY_KEY 即阿里云账号的 AccessKeys 信息,可以在阿里云官网控制台创建。 OSS_BUCKET 可以在 OSS 的控制台创建,用于存储渲管自身的 worker 包已经渲染数据。 渲管默认使用青岛(华北1)区域,如果使用其他区域的 BatchCompute,请修改配置中的OSS_HOST(OSS_BUCKET 必须与 OSS_HOST 属于同一个region)与 BATCHCOMPUTE_REGION,每个 REGION 的 OSS_HOST 也可以工单咨询获取。 区域的选择和计算节点的镜像区域保持一致,若计算节点镜像在深圳区域,则渲管的区域信息也必须是深圳,同时 OSS BUCKET 也必须是该 REGION 下的 BUCKET;若使用批量计算官方提供的计算节点镜像则需要选择深圳 REGION。p45 其他配置项,请参考页面上的说明。 OSS数据上传 提交渲染作业前,一定要将渲染用到的数据上传 OSS,在计算节点启动后再上传的数据将不能在计算节点中访问到。 由于 OSS 页面控制台上传数据有大小限制,所以上传数据建议使用 OSS 的 命令行工具(类 linux系统)、windows 客户端或者 MAC 客户端 。 参考 更多 OSS工具 。 计算节点镜像制作 渲染客户如希望定制计算节点镜像,请参考:自定义镜像。 计算节点镜像管理 A) 添加计算节点镜像 在镜像管理页面,可以添加计算节点镜像 ID。add_image B) 给计算节点镜像配置渲染软件信息 在添加完计算节点镜像 ID 后,在镜像信息页面可以点击添加软件并配置软件信息。image_config 在配置软件信息时,需要填入渲染软件的名称,渲染文件的后缀(用于识别渲染文件)以及执行代码。 执行代码(要求 python 语法)会在渲管 worker 中执行,render_cmd 变量即渲染时的命令行,命令行应根据实际安装的渲染软件来填写,比如渲染软件的路径,以及一些参数。渲管中的模板只是个示例,实际使用需要微调。 render_cmd 渲管已经预定义了一些变量和函数,在执行代码中可以调用这些变量和函数,例如$CPU在执行期会被替换成实际的cpu核数,$START_FRAME在执行期会被替换成起始帧号。 如果想增加自定义参数,可以选择添加参数,添加的自定义参数会需要在提交作业时填入。关于所有的可用变量可在软件配置页面点击查看。 $OUTPUT_LOCAL_DIR这个变量即创建项目时配置的节点内临时输出路径,渲染的输出结果应该放在该路径下(大部分渲染器都支持在命令行中指定输出路径),在渲染结束后该目录下的数据会被传输到 OSS。 项目管理 A) 项目创建 创建项目时需要指定 OSS 数据映射,计算节点镜像,虚拟机内的临时输出路径,OSS 输出路径。 i. 计算节点镜像 创建项目时选择的计算节点镜像(需要先在镜像管理页面添加计算节点镜像)是提交 AutoCluster 作业时使用的镜像,如果提交作业时指定了集群(在集群管理页面可以创建)则作业直接跑在所指定的集群中。 ii. OSS数据映射 OSS 数据映射(或者称 OSS 数据挂载),可以将 OSS 上的数据映射到计算节点的本地路径(windows 是盘符),一个作业中的所有计算节点可以共享访问到相同的数据。OSS 数据挂载有如下功能或限制: 映射的目的路径必须根据计算节点镜像实际的操作系统类型进行填写,否则会导致挂载失败,windows 只能映射到盘符(例 G:),linux 必须是绝对路径。 可共享读取访问 OSS 上的数据。 不支持修改 OSS 上已存在的文件和文件夹名称。 选择 WriteSupport 后,支持本地(挂载路径下)文件和文件夹的创建,以及新建文件的修改。 挂载的本地路径里的改动只是本计算节点可见,不会同步到 OSS。 在 Windows 系统中,在挂载时刻已存在的文件夹中创建的文件或文件夹将不支持删除操作,linux 系统可以。 选择 LockSupport 后,将可以使用文件锁功能(只影响 windows)。 OSS 数据挂载会有分布式cache(集群内),所以在大规模并发读取数据时性能较好(能达到 10MB~30MB,200 台并发,读取 20G 数据)。 OSS 路径必须以’/’结尾。 iii. OSS 输出目录与临时本地输出目录 渲染作业结束时,计算节点中的临时输出目录中的数据将会被传输到 OSS 输出目录中。临时输出路径格式必须与节点的操作系统类型对应,不然会出错。 B) 提交渲染任务 p41选择目的集群和场景所在的 OSS 路径前缀后进入提交的详细页面,选中场景文件的上一级目录,可以被提交渲染的场景文件则会被列出,勾选想要渲染的文件,选择配置的渲染软件和起止帧,即可提交渲染作业。 可指定节点数量,如果指定集群,并发数量上限是集群的节点数上限。填入的起止帧会均匀的分布在各个计算节点被渲染。p42 任务结束后可以在OSS上查看输出结果,如果开启自动下载(配置页面设置),渲管会在任务结束后将OSS上的输出结果下载到渲管部署的机器上。 C) 渲染日志 在节点列表页面,点击节点可以查看各种日志,渲管 worker 日志里都是渲管系统 worker 的日志,里面可以查看该计算节点中运行的实际渲染命令行。 渲染器标准输出和渲染器标准输出里的日志,就是渲染软件的输出日志。 p47 调试 新启动的渲管需要进行配置,并进行调试然后再提交大规模的渲染任务。 配置完,应该先提交1帧测试任务,查看错误日志(渲管 worker 日志和渲染器标准输出)调整渲染软件配置(主要是修改渲染命令行),走通全流程并确认结果没有问题后才进行正式生产渲染。 当作业失败的时候可以在作业信息中查看失败原因项。p46 建议创建一个集群然后将作业提交到该集群进行调试(AutoCluster 的作业需要启停计算节点,比较费时)。 集群管理 在集群管理页面可以创建自定义集群,需要选择所需的计算节点镜像 ID,节点的实例类型(BatchCompute 的不同区域可能支持的实例类型和磁盘类型不同,详细可以提工单咨询)。 磁盘类型和磁盘大小(根据实际制作的计算节点镜像的磁盘大小选择,选择过小会导致无法启动计算节点)。创建好的集群可以动态调整节点数量,甚至调整数量到 0。p48

1934890530796658 2020-03-28 20:45:20 0 浏览量 回答数 0

问题

如何保存服务器读取渲染后的页面:报错

kun坤 2020-06-08 18:51:05 0 浏览量 回答数 1

回答

我也是jade,不过我是用jade开发的直接用gulp编译,上线的是直接编译好的HTML。错了会直接提示到某行,自动的,我感觉没有这么费劲。在我看来,前端的模板会在3个场合用到。开发的时候上线的时候(服务端渲染)上线的时候(浏览器渲染)我属于第一种,所以选了jade。我之前也是一直用的emmet,说实话节约了一些时间,但很多问题还是没有解决。emmet让写dom的速度升级了,但没有让改dom的和看dom速度升级,特别是dom在一屏幕看不完的时候。但对于每一个人都要分清场景再选择,小的模板underscore和lodash就可解决。如果你用了angular或者是react的框架,本身会有模板的功能。

杨冬芳 2019-12-02 02:50:35 0 浏览量 回答数 0

回答

chromd和firfox的debug工具都挺强的,你可以看看 渲染之后的网页是不是更改了你的href.一般来讲,tomcat会自动的在href上加上项目地址如:http://localhost:8080/***/

小旋风柴进 2019-12-02 02:06:27 0 浏览量 回答数 0

回答

# flask中的信号blinker 信号主要是让开发者可是在flask请求过程中定制一些行为。 或者说flask在列表里面预留了几个空列表,在里面存东西。 简言之,信号允许某个'发送者'通知'接收者'有事情发生了 @before_request有返回值,blinker没有返回值 # 10个信号 request_started = _signals.signal('request-started') #请求到来前执行 request_finished = _signals.signal('request-finished') #请求结束后执行 before_render_template = _signals.signal('before-render-template') #模板渲染前执行 template_rendered = _signals.signal('template-rendered') #模板渲染后执行 got_request_exception = _signals.signal('got-request-exception') #请求执行出现异常时执行 request_tearing_down = _signals.signal('request-tearing-down') #请求执行完毕后自动执行(无论成功与否) appcontext_tearing_down = _signals.signal('appcontext-tearing-down') #请求上下文执行完毕后自动执行(无论成功与否) appcontext_pushed = _signals.signal('appcontext-pushed') #请求app上下文push时执行 appcontext_popped = _signals.signal('appcontext-popped') #请求上下文pop时执行 message_flashed = _signals.signal('message-flashed')#调用flask在其中添加数据时,自动触发

珍宝珠 2019-12-02 03:20:29 0 浏览量 回答数 0

回答

在确定问题原因和有问题的浏览器后,使用单独的样式表,仅供出现问题的浏览器加载。这种方法需要使用服务器端渲染。 使用已经处理好此类问题的库,比如 Bootstrap。 使用 autoprefixer 自动生成 CSS 属性前缀。 使用 Reset CSS 或 Normalize.css。

茶什i 2019-12-02 03:17:03 0 浏览量 回答数 0

回答

生命周期就是vue从开始创建到销毁的过程,分为四大步(创建,挂载,更新,销毁),每一步又分为两小步,如beforeCreate,created。beforeCreate前,也就是new Vue的时候会初始化事件和生命周期;beforeCreate和created之间会挂载Data,绑定事件;接下来会根据el挂载页面元素,如果没有设置el则生命周期结束,直到手动挂载;el挂载结束后,根据templete/outerHTML(el)渲染页面;在beforeMount前虚拟DOM已经创建完成;之后在mounted前,将vm.$el替换掉页面元素el;mounted将虚拟dom挂载到真实页面(此时页面已经全部渲染完成);之后发生数据变化时触发beforeUpdate和updated进行一些操作;最后主动调用销毁函数或者组件自动销毁时beforeDestroy,手动撤销监听事件,计时器等;destroyed时仅存在Dom节点,其他所有东西已自动销毁 问题来源于GitHub,查看更多答案,请查看https://github.com/haizlin/fe-interview/issues/229

游客7iokfgo4yexey 2020-05-24 12:14:07 0 浏览量 回答数 0

问题

阿里云助力国内首部云计算渲染的动画《昆塔·盒子总动员》的制作

看头像 2019-12-01 21:24:37 8384 浏览量 回答数 6

回答

Next.js是一个流行的轻量级框架,用于使用React构建的静态和服务器渲染应用程序。它还提供样式和路由解决方案。以下是NextJS提供的主要功能, 默认情况下由服务器呈现 自动代码拆分可加快页面加载速度 简单的客户端路由(基于页面) 支持(HMR)的基于Webpack的开发环境 能够与Express或任何其他Node.js HTTP服务器一起实现 可使用您自己的Babel和Webpack配置进行自定义

你的答案 2020-05-08 11:04:17 0 浏览量 回答数 0

问题

【视频】前端网络(性能)监测工具 berserkJS

随歌 2019-12-01 22:06:18 11102 浏览量 回答数 0

问题

如何打包场景

sophi5a 2019-12-01 20:01:50 10027 浏览量 回答数 2

回答

这个key应该是data-reactid有关系,这个data-reactid是react自动生成为dom-diff算法服务的,你打开react生成的html里面能看得见。添加key应该是保证react-vdom的标识唯一性,你应该发现只有添加一批完全一样的component在同一节点下才会有这个warning。react的diff算法,每次render的时候都会根据这个唯一标记的dom来决定是否要重新渲染这部分,以此来达到减少不需要的dom操作,提高性能的目的。你可以试一下,react的组件在update的时候性能明显好于其他框架你添加了一些你认为唯一性的数据但是没起到作用,很可能是数据在你不知道的地方有重复的原因想省事就放个index肯定可以去掉warning

a123456678 2019-12-02 02:07:13 0 浏览量 回答数 0

回答

Flutter开发框架总结 跨平台高性能的渲染引擎逐渐成为移动端、大前端领域的一个热点,作为其中的明星框架Flutter,经过近几年来的迅速发展,由极大的可能成为下一代跨终端解决方案。自从2017年5月,谷歌公司发布了alpha版本的Flutter;2018年底Flutter Live发布的1.0版本;2019年7月发布1.5版本,截至今日(2020年2月)已经发布了v1.14.6Beta版本。 Flutter背景 + 发展历程 首先在写Flutter之前我们要了解什么是原生开发什么是跨平台技术: 原生开发     是指在某一个平台所特有的应用,使用该平台所支持的开发工具和语言,并直接调用系统SDK,比如android上使用java 和ios上使用OC来开发, 这样做的好处 是可以使用平台上全部功能、速度快 性能好,用户体验好。 但是 缺点也很明显,开发不同平台需要维护的成本增加,动态化弱,更新时需要发布版本。 跨平台技术     针对原生开发所遇到的问题,人们已经研究出现有的跨平台技术方案:H5+原生、Js开发加原生渲染(例如React Native、weex等)、自绘UI加原生(QT fro mobile,Flutter) 发展历程     2011年谷歌推出一款可以在移动端,web,服务器等领域的语言—dart,其本质目的是为了取代现在的js的web。 1. 2014年谷歌在github开源了Sky 这便是Flutter的前身 2. 2015-10 Sky改名为Flutter 3. 2017-5 谷歌正式向外界公布Flutter 4. 2018-12 谷歌发布Flutter Live的1.0版本 5. 2019-2 Flutter1.2发布主要是增加对web的支持     Flutter提供了丰富的组件、接口,开发者可以很快地为 Flutter添加 native扩展。同时 Flutter还使用 Native引擎渲染视图,这无疑能为用户提供良好的体验 Flutter架构     Flutter既没有采用Webview也没有采用操作系统的原生控件,相反Flutter使用自己的高性能渲染引擎来绘制widget,这样不仅可以保证UI和原生的一致性,也可以降低维护成本。     Flutter使用Skia作为其2D渲染引擎,Skia是谷歌的一个2D图形处理函数库。     Flutter 采用Dart语言进性开发。Dart在即时编译模式下速度与JavaScript基本持平,但是Dart支持AOT(Ahead-Of-Time - 预先编译),如果以AOT模式运行时js便远追不上了。 为什么Flutter语言采用Dart而不是JavaScript,我们需要做一个对比 1. 开发效率 Dart运行时和编译器支持Flutter的两个关键特性的组合—“基于JIT的快速开发周期”、“基于AOT的发布包” 2. 高性能 Flutter为了实现流畅高保真的UI体验,需要能够在每个动画帧中运行大量的代码,这就需要一种既能提供高性能的语言,又不会出现丢帧,在这一点上Dart更好 3. 快速分配内存 Flutter框架使用函数式流,这使得它很依赖于底层的内存分配器。事实上Dart开发团队许多来自chrome,chrome V8的js引擎在内存分配上也做得非常好,而Dart也正好满足 4. 类型安全 Dart是类型安全语言,支持静态类型检测,js是弱类型语言,这是Dart的一个重要优势 言归正传,下图是Flutter官方提供的一个架构图 引擎刚刚已经介绍过了,我们现在来看看Flutter框架的结构:     由下到上     Foundation、Animation、Painting、Gestutes 这些在Google的一些视频中合称为Dart ui层,对应的是Flutter中的dart:ui包,他是底层ui库,提供动画、手势以及绘制能力。     Rendering层为一个抽象的布局层,它依赖于ui层,这类似于react中的虚拟dom树,该层可以说是Flutter框架最核心的部分,它除了确定每个元素的位置、大小还要进性坐标变换、绘制。     Widgets层是一套基础组件库,在基础组件之上还提供了Material和Cupertino两种视觉风格组件库,大多数我们只是使用这两层。 Flutter运行流程 渲染流程     当需要更新UI的时候,Framework通知Engine,Engine会等到下个Vsync信号到达的时候,会通知Framework,然后Framework会进行animations, build,layout,compositing,paint,最后生成layer提交给Engine。Engine会把layer进行组合,生成纹理,最后通过Open Gl接口提交数据给GPU, GPU经过处理后在显示器上面显示。 启动流程     此图为flutter在安卓下启动的流程,在安卓中默认启动的Activity是MainActivity,而MainActivity继承的是Flutter Activity。     FlutterActivity是继承Activity和实现了PluginRegistry。分析一下onCreate,onStop,onDestroy这些生命周期方法被FlutterActivity.eventDelegate代理了,这个时候我们明白了,FlutterActivity就是一个空壳,真正实现是代理类FlutterActivityDelegate。说白了就是创建一个FlutterView,并且把view显示到屏幕上。 Flutter生命周期     Flutter和安卓、ios应用一样拥有自己的生命周期,对比来看,安卓中是Activity,ios中是ViewController。Flutter中为Widget createState(): 当框架构建StatefulWidget时,会立即调用createState();initState(): 创建窗口小部件时,调用的第一个方法,子类化State可以重写initState,用来完成仅需要执行一次的工作。didChangeDependencies(): 在执行完initState之后调用此方法。build(): 在执行完didChangeDependencies() 之后立即调用,所有的GUI都会在这里渲染,并且每次渲染UI时都会调用它。didUpdateWidget(): 父级窗口小部件进行更改并需要重新绘制UI时,会调用此方法setState(): 此方法用于通知框架数据已更改。dispose(): 销毁方法,移除State对象时调用,应该在此方法中取消一些订阅、动画、流等。 Flutter生态圈及其常用框架 DIO Dio是flutter中文网开源的一个强大的Dart Http请求库,支持Restful Api、FormData、拦截器、请求取消、Cookie、文件上传下载、超时等。 Flukit flukit即Flutter UI Kit,一个常用的Widget库,包括下拉刷新、轮播图、快速滚动条、渐变进度条、城市选择器等. CookieJar 一个实现HTTP协议标准Cookie管理策略的Cookie管理器,他可以自动帮您自动管理http请求cookie,并支持本地持久化。 flutter-go 阿里巴巴开源的flutter 开发者帮助 APP,包含 flutter 常用 140+ 组件的demo 演示与中文文档 https://flutter-go.pub/website/ Best-Flutter-UI-Templates Github地址:https://github.com/mitesh77/Best-Flutter-UI-Templates ,有许多内置ui模板。 欢迎大家有问题随时和我分享哦~初次在开发者社区码字,若有不足之处,请指教,您的每一次留言都是我前进的动力。愿大家在疫情期间共同进步,共创美好的开发者社区。

kun坤 2020-03-02 17:00:55 0 浏览量 回答数 0

问题

如何给网页和APP提速?——性能极客

陈阿达 2019-12-01 22:05:01 6380 浏览量 回答数 0

问题

申请的ssl,如何结合php来使用?

落地花开啦 2019-12-01 19:56:50 1244 浏览量 回答数 2

回答

AliyunVodPlayer 类名:AliyunVodPlayer 功能:高级播放器的管理类,用于创建播放器实例。 成员: 成员 功能 prepareWithVid: accessKeyId: accessKeySecret: securityToken: 临时AccessKeyId、AccessKeySecret和SecurityToken:开启RAM授权,并通过STS授权系统提供的OpenAPI或SDK获取的AccessKeyId、AccessKeySecret和SecurityToken,用于播放和下载请求(V3.2.0版起推荐使用STS的播放方式)。 prepareWithVid:playAuth: 初始化设置vid(视频id)和playauth(播放凭证-通过用户服务端下发) prepareWithUrl 根据视频url获取视频信息,准备播放 playerView 获取视频显示view displayMode 获取/设置当前显示模式 autoPlay 获取/设置是否自动播放 quality 获取/设置视频清晰度 muteMode 设置是否静音 isPlaying 获取播放器是否播放 timeout 当播放网络流时,设置网络超时时间,默认15000毫秒 playerState 获取播放器当前状态 start 开始播放 resume 继续播放 pause 暂停播放 stop 停止播放 replay 重新播放 duration 视频总时长 seekToTime 拖动到的时间点 currentTime 视频播放当前时间 loadedTime 视频已经加载的时间 setAliyunVodPlayerDelegate 设置播放状态回调代理 getAliyunMediaInfo 获取媒体信息, 当AliyunVodPlayerEventPrepareDone时,才能获取到该参数对象 setPlayingCache 设置边播边缓存功能 videoWidth 获取视频宽度,只读属性。 videoHeight 获取视频高度,只读属性。 pringtLog 日志开关。 brightness 亮度,调用brightness系统属性,brightness(0~1.0)。 volume 声音调节,调用系统MPVolumeView类实现,并非视频声音;volume(0~1.0)。 playSpeed 设置倍数播放值,可设置为0.5~2 getSDKVersion 获取SDK版本号 circlePlay 循环播放控制 snapshot 截取当前正在播放图像 setRenderRotate 渲染视图角度 setRenderMirrorMode 渲染镜像 liveTime 直播时移,直播时间 currentPlayTime 直播时移,播放时间 timeShiftModel 直播时移,更新的时移数据 prepareWithLiveTimeUrl:liveTimeUrl 直播时移准备播放 setLiveTimeShiftUrl:liveTimeShiftUrl 直播时移,直播时移地址 seekToLiveTime:startTime 直播时移,seek到startTime播放时间 referer 防盗链参数

python小菜菜 2020-06-19 13:24:20 0 浏览量 回答数 0

问题

jfinal2.1新的BaseModel后台渲染问题及解决方案?报错

爱吃鱼的程序员 2020-06-10 15:03:50 0 浏览量 回答数 1

问题

【Cocos3d 入门教程之---配置cocos3d环境】 : 配置报错 

kun坤 2020-06-03 17:47:35 27 浏览量 回答数 1

回答

支持在Ubuntu8.10、Ubuntu9.04系统上自动安装微软雅黑、monaco-linux、lucida-console等字体。 而且可以设置LED、CRT两种不同的显示器的渲染效果,无需手工配置,实现自动化安装。 使用方法如下: 打开命令控制台,然后运行下面的脚本(可以通过复制下面的内容到命令控制台来执行脚本): wget -O get-fonts.sh.zip http://files.cnblogs.com/DengYangjun/get-fonts.sh.zip unzip -o get-fonts.sh.zip 1>/dev/null chmod a x get-fonts.sh ./get-fonts.sh 删除下载的字体安装脚本文件: rm get-fonts.sh get-fonts.sh.zip 2>/dev/null 恢复以前的字体设置: cd /etc/fonts/conf.avail sudo mv 51-local.conf.old 51-local.conf 2>/dev/null sudo mv 69-language-selector-zh-cn.conf.old 69-language-selector-zh-cn.conf 2>/dev/null sudo rm -f -r /usr/share/fonts/truetype/myfonts 2>/dev/null cd -

大脸猫 2019-12-02 01:58:36 0 浏览量 回答数 0

回答

#- 路由,自动帮助开发者快速为一个视图创建4个url www.oldboyedu.com/api/v1/student/$ www.oldboyedu.com/api/v1/student(?P<format>\w+)$ www.oldboyedu.com/api/v1/student/(?P<pk>\d+)/$ www.oldboyedu.com/api/v1/student/(?P<pk>\d+)(?P<format>\w+)$ #- 版本处理 - 问题:版本都可以放在那里? - url - GET - 请求头 #- 认证 - 问题:认证流程? #- 权限 - 权限是否可以放在中间件中?以及为什么? #- 访问频率的控制 匿名用户可以真正的防止?无法做到真正的访问频率控制,只能把小白拒之门外。 如果要封IP,使用防火墙来做。 登录用户可以通过用户名作为唯一标示进行控制,如果有人注册很多账号,则无法防止。 #- 视图 #- 解析器 ,根据Content-Type请求头对请求体中的数据格式进行处理。request.data #- 分页 #- 序列化 - 序列化 - source - 定义方法 - 请求数据格式校验 #- 渲染器

珍宝珠 2019-12-02 03:20:27 0 浏览量 回答数 0

回答

从效果图上我们还看到有几点重要信息: 点赞动画图片大小不一,运动轨迹也是随机的点赞动画图片都是先放大再匀速运动。快到顶部的时候,是渐渐消失。收到大量的点赞请求的时候,点赞动画不扎堆,井然有序持续出现。 那么如何实现这些要求呢?下面介绍两种实现方式来实现(底部附完整 demo): CSS3 实现 用 CSS3 实现动画,显然,我们想到的是用 animation 。 首先看下 animation 合并写法,具体含义就不解释了,如果需要可以自行了解。 animation: name duration timing-function delay iteration-count direction fill-mode play-state; 我们开始来一步一步实现。 Step 1: 固定区域,设置基本样式 首先,我们先准备 1 张点赞动画图片: 看一下 HTML 结构。外层一个结构固定整个显示动画区域的位置。这里在一个宽 100px ,高 200px 的 div 区域。 Step 5: 设置偏移 我们先定义帧动画:bubble_1 来执行偏移。图片开始放大阶段,这里没有设置偏移,保持中间原点不变。 在运行到 25% * 4 = 1s,即 1s之后,是向左偏移 -8px, 2s 的时候,向右偏移 8px,3s 的时候,向做偏移 15px ,最终向右偏移 15px。 大家可以想到了,这是定义的一个经典的左右摆动轨迹,“向左向右向左向右” 曲线摆动效果。 @keyframes bubble_1 { 0% { } 25% { margin-left:-8px; } 50% { margin-left:8px } 75% { margin-left:-15px } 100% { margin-left:15px } } 效果如下: Step 6: 补齐动画样式 这里预设了一种运行曲线轨迹,左右摆动的样式,我们在再预设更多种曲线,达到随机轨迹的目的。 比如 bubble_1 的左右偏移动画轨迹,我们可以修改偏移值,来达到不同的曲线轨迹。 Step 7: JS 操作随机增加节点样式 提供增加点赞的方法,随机将点赞的样式组合,然后渲染到节点上。 let praiseBubble = document.getElementById("praise_bubble"); let last = 0; function addPraise() { const b =Math.floor(Math.random() * 6) + 1; const bl =Math.floor(Math.random() * 11) + 1; // bl1~bl11 let d = document.createElement("div"); d.className = bubble b${b} bl${bl}; d.dataset.t = String(Date.now()); praiseBubble.appendChild(d); } setInterval(() => { addPraise(); },300) 在使用 CSS 来实现点赞的时候,通常还需要注意设置 bubble 的随机延时,比如: .bl2{ animation:bubble_2 $bubble_time linear .4s 1 forwards,bubble_big_2 $bubble_scale linear .4s 1 forwards,bubble_y $bubble_time linear .4s 1 forwards; } 这里如果是随机到 bl2,那么延时 0.4s 再运行,bl3 延时 0.6s …… 如果是批量更新到节点上,不设置延时的话,那就会扎堆出现。随机“ bl ”样式,就随机了延时,然后批量出现,都会自动错峰显示。当然,我们还需要增加当前用户手动点赞的动画,这个不需要延时。 另外,有可能同时别人下发了点赞 40 个,业务需求通常是希望这 40 个点赞气泡都能依次出现,制造持续的点赞氛围,否则下发量大又会扎堆显示了。 那么我们还需要分批打散点赞数量,比如一次点赞的时间($bubble_time)是 4s, 那么 4s 内,希望同时出现多少个点赞呢?比如是 10个,那么 40 个点赞,需要分批 4 次渲染。 window.requestAnimationFrame(() => { // 继续循环处理批次 render(); }); 另外还需要手动清除节点。以防节点过多带来的性能问题。如下是完整的效果图。 class ThumbsUpAni{ constructor(){ const canvas = document.getElementById('thumsCanvas'); this.context = canvas.getContext('2d')!; this.width = canvas.width; this.height = canvas.height; } } Step 2:创建渲染对象 实时渲染图片,使其变成一个连贯的动画,很重要的是:生成曲线轨迹。这个曲线轨迹需要是平滑的均匀曲线。 假如生成的曲线轨迹不平滑的话,那看到的效果就会太突兀,比如上一个是 10 px,下一个就是 -10px,那显然,动画就是忽左忽右左右闪烁了。 理想的轨迹是上一个位置是 10px,接下来是 9px,然后一直平滑到 -10px,这样的坐标点就是连贯的,看起来动画就是平滑运行。 随机平滑 X 轴偏移 如果要做到平滑曲线,其实可以使用我们再熟悉不过的正弦( Math.sin )函数来实现均匀曲线。 看下图的正弦曲线: 这是 Math.sin(0) 到 Math.sin(9) 的曲线图走势图,它是一个平滑的从正数到负数,然后再从负数到正数的曲线图,完全符合我们的需求,于是我们再需要生成一个随机比率值,让摆动幅度随机起来。 const angle = getRandom(2, 10); let ratio = getRandom(10,30)*((getRandom(0, 1) ? 1 : -1)); const getTranslateX = (diffTime) => { if (diffTime < this.scaleTime) {// 放大期间,不进行摇摆偏移 return basicX; } else { return basicX + ratio*Math.sin(angle*(diffTime - this.scaleTime)); } }; 复制代码scaleTime 是从开始放大到最终大小,用多长时间,这里我们设置 0.1,即总共运行时间前面的 10% 的时间,点赞图片逐步放大。 diffTime,是只从开始动画运行到当前时间过了多长时间了,为百分比。实际值是从 0 --》 1 逐步增大。 diffTime - scaleTime = 0 ~ 0.9, diffTime 为 0.4 的时候,说明是已经运行了 40% 的时间。 因为 Math.sin(0) 到 Math.sin(0.9) 曲线几乎是一个直线,所以不太符合摆动效果,从 Math.sin(0) 到 Math.sin(1.8) 开始有细微的变化,所以我们这里设置的 angle 最小值为 2。 这里设置角度系数 angle 最大为 10 ,从底部到顶部运行两个波峰。 当然如果运行距离再长一些,我们可以增大 angle 值,比如变成 3 个波峰(如果时间短,出现三个波峰,就会运行过快,有闪烁现象)。如下图: Y 轴偏移 这个容易理解,开始 diffTime 为 0 ,所以运行偏移从 this.height --> image.height / 2。即从最底部,运行到顶部留下,实际上我们在顶部会淡化隐藏。 const getTranslateY = (diffTime) => { return image.height / 2 + (this.height - image.height / 2) * (1-diffTime); }; 复制代码放大缩小 当运行时间 diffTime 小于设置的 scaleTime 的时候,按比例随着时间增大,scale 变大。超过设置的时间阈值,则返回最终大小。 const basicScale = [0.6, 0.9, 1.2][getRandom(0, 2)]; const getScale = (diffTime) => { if (diffTime < this.scaleTime) { return +((diffTime/ this.scaleTime).toFixed(2)) * basicScale; } else { return basicScale; } }; 复制代码淡出 同放大逻辑一致,只不过淡出是在运行快到最后的位置开始生效。 **const fadeOutStage = getRandom(14, 18) / 100; const getAlpha = (diffTime) => { let left = 1 - +diffTime; if (left > fadeOutStage) { return 1; } else { return 1 - +((fadeOutStage - left) / fadeOutStage).toFixed(2); } }; ** 实时绘制 创建完绘制对象之后,就可以实时绘制了,根据上述获取到的“偏移值”,“放大”和“淡出”值,然后实时绘制点赞图片的位置即可。 每个执行周期,都需要重新绘制 canvas 上的所有的动画图片位置,最终形成所有的点赞图片都在运动的效果。 createRender(){ return (diffTime) => { // 差值满了,即结束了 0 ---》 1 if(diffTime>=1) return true; context.save(); const scale = getScale(diffTime); const translateX = getTranslateX(diffTime); const translateY = getTranslateY(diffTime); context.translate(translateX, translateY); context.scale(scale, scale); context.globalAlpha = getAlpha(diffTime); // const rotate = getRotate(); // context.rotate(rotate * Math.PI / 180); context.drawImage( image, -image.width / 2, -image.height / 2, image.width, image.height ); context.restore(); }; } 这里绘制的图片是原图的 width 和 height。前面我们设置了 basiceScale,如果图片更大,我们可以把 scale 再变小即可。 const basicScale = [0.6, 0.9, 1.2][getRandom(0, 2)]; 实时绘制扫描器 开启实时绘制扫描器,将创建的渲染对象放入 renderList 数组,数组不为空,说明 canvas 上还有动画,就需要不停的去执行 scan,直到 canvas 上没有动画结束为止。 scan() { this.context.clearRect(0, 0, this.width, this.height); this.context.fillStyle = "#f4f4f4"; this.context.fillRect(0,0,200,400); let index = 0; let length = this.renderList.length; if (length > 0) { requestAnimationFrame(this.scan.bind(this)); } while (index < length) { const render = this.renderList[index]; if (!render || !render.render || render.render.call(null, (Date.now() - render.timestamp) / render.duration)) { // 结束了,删除该动画 this.renderList.splice(index, 1); length--; } else { // 当前动画未执行完成,continue index++; } } } 这里就是根据执行的时间来对比,判断动画执行到的位置了: diffTime = (Date.now() - render.timestamp) / render.duration 复制代码如果开始的时间戳是 10000,当前是100100,则说明已经运行了 100 毫秒了,如果动画本来需要执行 1000 毫秒,那么 diffTime = 0.1,代表动画已经运行了 10%。 增加动画 每点赞一次或者每接收到别人点赞一次,则调用一次 start 方法来生成渲染实例,放进渲染实例数组。如果当前扫描器未开启,则需要启动扫描器,这里使用了 scanning 变量,防止开启多个扫描器。 start() { const render = this.createRender(); const duration = getRandom(1500, 3000); this.renderList.push({ render, duration, timestamp: Date.now(), }); if (!this.scanning) { this.scanning = true; requestFrame(this.scan.bind(this)); } return this; } 这里开启定时器,记录定时器里面处理的 thumbsStart 的值,如果有新增点赞,且定时器还在运行,直接更新最后的 praiseLast 值,定时器会依次将点赞请求全部处理完。 定时器的延时时间 time 根据开启定时器的时候,需要渲染多少点赞动画来决定的,比如需要渲染 100 个点赞动画,我们将 100 个点赞动画分布在 5s 内渲染完。 对于热门直播,会同时渲染的动画很多,不会扎堆显示,且动画完全能衔接上,不停的冒泡点赞动画。对于冷门直播,有多余一个的点赞请求,我们能打散到 5s 内显示,也不会扎堆显示。 End 两种方式渲染点赞动画都已经完成,完整源码,源码戳这里 。 源码运行效果图: 再比较 这两种实现方式,都可以满足要求,那么到底哪种更优呢? 我们来看下两者的数据对比。以下为未开启硬件加速的对比,采用不间断疯狂渲染点赞动画的数据对比: 整体来说,差异如下: CSS3 实现简单Canvas 更灵活,操作更细腻CSS3 内存消耗比 Canvas 大,如果开启硬件加速,内存消耗更大一些。

剑曼红尘 2020-04-15 19:17:18 0 浏览量 回答数 0

回答

浏览器渲染机制 浏览器采用流式布局模型(Flow Based Layout)浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了渲染树(Render Tree)。有了RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,他们可能需要多次计算,通常要花3倍于同等元素的时间,这也是为什么要避免使用table布局的原因之一。 重绘 由于节点的几何属性发生改变或者由于样式发生改变而不会影响布局的,称为重绘,例如outline, visibility, color、background-color等,重绘的代价是高昂的,因为浏览器必须验证DOM树上其他节点元素的可见性。 回流 回流是布局或者几何属性需要改变就称为回流。回流是影响浏览器性能的关键因素,因为其变化涉及到部分页面(或是整个页面)的布局更新。一个元素的回流可能会导致了其所有子元素以及DOM中紧随其后的节点、祖先节点元素的随后的回流。 <body> <div class="error"> <h4>我的组件</h4> <p><strong>错误:</strong>错误的描述…</p> <h5>错误纠正</h5> <ol> <li>第一步</li> <li>第二步</li> </ol> </div> </body> 在上面的HTML片段中,对该段落(p标签)回流将会引发强烈的回流,因为它是一个子节点。这也导致了祖先的回流(div.error和body – 视浏览器而定)。此外,h5和ol也会有简单的回流,因为其在DOM中在回流元素之后。大部分的回流将导致页面的重新渲染。 回流必定会发生重绘,重绘不一定会引发回流。 浏览器优化 现代浏览器大多都是通过队列机制来批量更新布局,浏览器会把修改操作放在队列中,至少一个浏览器刷新(即16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能有会影响这些属性或方法返回值的操作,即使没有,浏览器也会强制清空队列,触发回流与重绘来确保返回正确的值。 主要包括以下属性或方法: - offsetTop、offsetLeft、offsetWidth、offsetHeight - scrollTop、scrollLeft、scrollWidth、scrollHeight - clientTop、clientLeft、clientWidth、clientHeight - width、height - getComputedStyle() - getBoundingClientRect() 所以,我们应该避免频繁的使用上述的属性,他们都会强制渲染刷新队列。 减少重绘与回流 CSS 使用 transform 替代 top使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局)避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局。尽可能在DOM树的最末端改变class,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围,使其影响尽可能少的节点。 避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。 <div> <a> <span></span> </a> 对于第一种设置样式的方式来说,浏览器只需要找到页面中所有的 span 标签然后设置颜色,但是对于第二种设置样式的方式来说,浏览器首先需要找到所有的 span 标签,然后找到 span 标签上的 a 标签,最后再去找到 div 标签,然后给符合这种条件的 span 标签设置颜色,这样的递归过程就很复杂。所以我们应该尽可能的避免写过于具体的 CSS 选择器,然后对于 HTML 来说也尽量少的添加无意义标签,保证层级扁平。 - 将动画效果应用到position属性为absolute或fixed的元素上,避免影响其他元素的布局,这样只是一个重绘,而不是回流,同时,控制动画速度可以选择 requestAnimationFrame,详见探讨 requestAnimationFrame。 - 避免使用CSS表达式,可能会引发回流。 - 将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点,例如will-change、video、iframe等标签,浏览器会自动将该节点变为图层。 - CSS3 硬件加速(GPU加速),使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘 。但是对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。 2. Javascript - 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。 - 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。 - 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。 - 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。

九旬 2020-05-24 11:22:47 0 浏览量 回答数 0

问题

性能极客:全新UI,全新功能,全新出发!

陈阿达 2019-12-01 21:29:27 7568 浏览量 回答数 1

问题

模板,从服务端到客户端

go696 2019-12-01 21:32:31 3535 浏览量 回答数 0

回答

准备工作 1.1. 选择区域 所有阿里云服务都需要使用相同的地域。 1.2. 开通服务 开通批量计算服务(BatchCompute); 开通对象存储服务(OSS)。 1.3. 制作镜像 制作镜像具体步骤请参考集群镜像, 请严格按文档的步骤创建镜像。镜像制作完成后,通过以下方式可以获取到对应的镜像信息。 image 1.4. 上传素材 可以下载 3ds Max 官方提供的免费素材包进行测试。 通过 OSSBrowser 工具将渲染素材到指定的 OSS bucket 中,如下图: upload 1.5. 安装批量计算 SDK 在需要提交作业的机器上,安装批量计算 SDK 库;已经安装请忽略。Linux 安装执行如下命令;Windows 平台请参考文档。 pip install batchcompute 2. 编写work脚本 work.py #!/usr/bin/env python -- coding: UTF-8 -- import os import math import sys import re import argparse NOTHING_TO_DO = 'Nothing to do, exit' def _calcRange(a,b, id, step): start = min(id * step + a, b) end = min((id+1) * step + a-1, b) return (start, end) def _parseContinuedFrames(render_frames, total_nodes, id=None, return_type='list'): ''' 解析连续帧, 如: 1-10 ''' [a,b]=render_frames.split('-') a=int(a) b=int(b) #print(a,b) step = int(math.ceil((b-a+1)*1.0/total_nodes)) #print('step:', step) mod = (b-a+1) % total_nodes #print('mod:', mod) if mod==0 or id < mod: (start, end) = _calcRange(a,b, id, step) #print('--->',start, end) return (start, end) if return_type!='list' else range(start, end+1) else: a1 = step * mod + a #print('less', a1, b, id) (start, end) = _calcRange(a1 ,b, id-mod, step-1) #print('--->',start, end) return (start, end) if return_type!='list' else range(start, end+1) def _parseIntermittentFrames(render_frames, total_nodes, id=None): ''' 解析不连续帧, 如: 1,3,8-10,21 ''' a1=render_frames.split(',') a2=[] for n in a1: a=n.split('-') a2.append(range(int(a[0]),int(a[1])+1) if len(a)==2 else [int(a[0])]) a3=[] for n in a2: a3=a3+n #print('a3',a3) step = int(math.ceil(len(a3)*1.0/total_nodes)) #print('step',step) mod = len(a3) % total_nodes #print('mod:', mod) if mod==0 or id < mod: (start, end) = _calcRange(0, len(a3)-1, id, step) #print(start, end) a4= a3[start: end+1] #print('--->', a4) return a4 else: #print('less', step * mod , len(a3)-1, id) (start, end) = _calcRange( step * mod ,len(a3)-1, id-mod, step-1) if start > len(a3)-1: print(NOTHING_TO_DO) sys.exit(0) #print(start, end) a4= a3[start: end+1] #print('--->', a4) return a4 def parseFrames(render_frames, return_type='list', id=None, total_nodes=None): ''' @param render_frames {string}: 需要渲染的总帧数列表范围,可以用"-"表示范围,不连续的帧可以使用","隔开, 如: 1,3,5-10 @param return_type {string}: 取值范围[list,range]。 list样例: [1,2,3], range样例: (1,3)。 注意: render_frames包含","时有效,强制为list。 @param id, 节点ID,从0开始。 正式环境不要填写,将从环境变量 BATCH_COMPUTE_DAG_INSTANCE_ID 中取得。 @param total_nodes, 总共的节点个数。正式环境不要填写,将从环境变量 BATCH_COMPUTE_DAG_INSTANCE_COUNT 中取得。 ''' if id==None: id=os.environ['BATCH_COMPUTE_DAG_INSTANCE_ID'] if type(id)==str: id = int(id) if total_nodes==None: total_nodes = os.environ['BATCH_COMPUTE_DAG_INSTANCE_COUNT'] if type(total_nodes)==str: total_nodes = int(total_nodes) if re.match(r'^(\d+)-(\d+)$',render_frames): # 1-2 # continued frames return _parseContinuedFrames(render_frames, total_nodes, id, return_type) else: # intermittent frames return _parseIntermittentFrames(render_frames, total_nodes, id) if name == "main": parser = argparse.ArgumentParser( formatter_class = argparse.ArgumentDefaultsHelpFormatter, description = 'python scripyt for 3dmax dag job', usage='render3Dmax.py [ ]', ) parser.add_argument('-s', '--scene_file', action='store', type=str, required=True, help = 'the name of the file with .max subffix .') parser.add_argument('-i', '--input', action='store', type=str, required=True, help = 'the oss dir of the scene_file, eg: xxx.max.') parser.add_argument('-o', '--output', action='store', type=str, required=True, help = 'the oss of dir the result file to upload .') parser.add_argument('-f', '--frames', action='store', type=str, required=True, help = 'the frames to be renderd, eg: "1-10".') parser.add_argument('-t', '--retType', action='store', type=str, default="test.jpg", help = 'the tye of the render result,eg. xxx.jpg/xxx.png.') args = parser.parse_args() frames=parseFrames(args.frames) framestr='-'.join(map(lambda x:str(x), frames)) s = "cd "C:\Program Files\Autodesk\3ds Max 2018\" && " s +='3dsmaxcmd.exe -o="%s%s" -frames=%s "%s\%s"' % (args.output, args.retType, framestr, args.input, args.scene_file) print("exec: %s" % s) rc = os.system(s) sys.exit(rc>>8) 注意: work.py 只需要被上传到 OSS bucket中不需要手动执行;各项参数通过作业提交脚本进行传递; work.py 的112 行需要根据镜像制作过程中 3ds MAX 的位置做对应替换; work.py 的 scene_file 参数表示场景文件;如 Lighting-CB_Arnold_SSurface.max; work.py 的 input 参数表示素材映射到 VM 中的位置,如: D; work.py 的 output 参数表示渲染结果输出的本地路径;如 C:\tmp\; work.py 的 frames 参数表示渲染的帧数,如: 1; work.py 的 retType 参数表示素材映射到 VM 中的位置,如: test.jpg;渲染结束后如果是多帧,则每帧的名称为test000.jpg,test001.jpg等。 work 编写作业提交脚本 test.py #!/usr/bin/env python -- coding: utf-8 -- from batchcompute import Client, ClientError from batchcompute.resources import ( ClusterDescription, GroupDescription, Configs, Networks, VPC, JobDescription, TaskDescription, DAG,Mounts, AutoCluster,Disks,Notification, ) import time import argparse from batchcompute import CN_SHANGHAI as REGION #需要根据 region 做适配 access_key_id = "xxxx" # your access key id access_key_secret = "xxxx" # your access key secret instance_type = "ecs.g5.4xlarge" # instance type #需要根据 业务需要 做适配 image_id = "m-xxx" workossPath = "oss://xxxxx/work/work.py" client = Client(REGION, access_key_id, access_key_secret) def getAutoClusterDesc(InstanceCount): auto_desc = AutoCluster() auto_desc.ECSImageId = image_id #任务失败保留环境,程序调试阶段设置。环境保留费用会继续产生请注意及时手动清除环境任务失败保留环境, # 程序调试阶段设置。环境保留费用会继续产生请注意及时手动清除环境 auto_desc.ReserveOnFail = False # 实例规格 auto_desc.InstanceType = instance_type #case3 按量 auto_desc.ResourceType = "OnDemand" #Configs configs = Configs() #Configs.Networks networks = Networks() vpc = VPC() # CidrBlock和VpcId 都传入,必须保证VpcId的CidrBlock 和传入的CidrBlock保持一致 vpc.CidrBlock = '172.26.0.0/16' # vpc.VpcId = "vpc-8vbfxdyhx9p2flummuwmq" networks.VPC = vpc configs.Networks = networks # 设置系统盘type(cloud_efficiency/cloud_ssd)以及size(单位GB) configs.add_system_disk(size=40, type_='cloud_efficiency') #设置数据盘type(必须和系统盘type保持一致) size(单位GB) 挂载点 # case1 linux环境 # configs.add_data_disk(size=40, type_='cloud_efficiency', mount_point='/path/to/mount/') # 设置节点个数 configs.InstanceCount = InstanceCount auto_desc.Configs = configs return auto_desc def getTaskDesc(inputOssPath, outputossPath, scene_file, frames, retType, clusterId, InstanceCount): taskDesc = TaskDescription() timestamp = time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime()) inputLocalPath = "D:" outputLocalPath = "C:\\tmp\\" + timestamp + "\\" outputossBase = outputossPath + timestamp + "/" stdoutOssPath = outputossBase + "stdout/" #your stdout oss path stderrOssPath = outputossBase + "stderr/" #your stderr oss path outputossret = outputossBase + "ret/" taskDesc.InputMapping = {inputOssPath: inputLocalPath} taskDesc.OutputMapping = {outputLocalPath: outputossret} taskDesc.Parameters.InputMappingConfig.Lock = True # 设置程序的标准输出地址,程序中的print打印会实时上传到指定的oss地址 taskDesc.Parameters.StdoutRedirectPath = stdoutOssPath # 设置程序的标准错误输出地址,程序抛出的异常错误会实时上传到指定的oss地址 taskDesc.Parameters.StderrRedirectPath = stderrOssPath #触发程序运行的命令行 # PackagePath存放commandLine中的可执行文件或者二进制包 taskDesc.Parameters.Command.PackagePath = workossPath taskDesc.Parameters.Command.CommandLine = "python work.py -i %s -o %s -s %s -f %s -t %s" % (inputLocalPath, outputLocalPath, scene_file, frames, retType) # 设置任务的超时时间 taskDesc.Timeout = 86400 # 设置任务所需实例个数 taskDesc.InstanceCount = InstanceCount # 设置任务失败后重试次数 taskDesc.MaxRetryCount = 3 if clusterId: # 采用固定集群提交作业 taskDesc.ClusterId = clusterId else: #采用auto集群提交作业 taskDesc.AutoCluster = getAutoClusterDesc(InstanceCount) return taskDesc def getDagJobDesc(inputOssPath, outputossPath, scene_file, frames, retType, clusterId = None, instanceNum = 1): job_desc = JobDescription() dag_desc = DAG() job_desc.Name = "testBatch" job_desc.Description = "test 3dMAX job" job_desc.Priority = 1 # 任务失败 job_desc.JobFailOnInstanceFail = False # 作业运行成功后户自动会被立即释放掉 job_desc.AutoRelease = False job_desc.Type = "DAG" render = getTaskDesc(inputOssPath, outputossPath, scene_file, frames, retType, clusterId, instanceNum) # 添加任务 dag_desc.add_task('render', render) job_desc.DAG = dag_desc return job_desc if name == "main": parser = argparse.ArgumentParser( formatter_class = argparse.ArgumentDefaultsHelpFormatter, description = 'python scripyt for 3dmax dag job', usage='render3Dmax.py [ ]', ) parser.add_argument('-n','--instanceNum', action='store',type = int, default = 1,help = 'the parell instance num .') parser.add_argument('-s', '--scene_file', action='store', type=str, required=True, help = 'the name of the file with .max subffix .') parser.add_argument('-i', '--inputoss', action='store', type=str, required=True, help = 'the oss dir of the scene_file, eg: xxx.max.') parser.add_argument('-o', '--outputoss', action='store', type=str, required=True, help = 'the oss of dir the result file to upload .') parser.add_argument('-f', '--frames', action='store', type=str, required=True, help = 'the frames to be renderd, eg: "1-10".') parser.add_argument('-t', '--retType', action='store', type=str, default = "test.jpg", help = 'the tye of the render result,eg. xxx.jpg/xxx.png.') parser.add_argument('-c', '--clusterId', action='store', type=str, default=None, help = 'the clusterId to be render .') args = parser.parse_args() try: job_desc = getDagJobDesc(args.inputoss, args.outputoss, args.scene_file, args.frames,args.retType, args.clusterId, args.instanceNum) # print job_desc job_id = client.create_job(job_desc).Id print('job created: %s' % job_id) except ClientError,e: print (e.get_status_code(), e.get_code(), e.get_requestid(), e.get_msg()) 注意: 代码中 12~20 行 需要根据做适配,如 AK 信息需要填写账号对应的AK信息;镜像Id 就是1.3 中制作的镜像 Id;workosspath 是步骤 2 work.py 在oss上的位置; 参数 instanceNum 表示 当前渲染作业需要几个节点参与,默认是1个节点;若是设置为多个节点,work.py 会自动做均分; 参数 scene_file 表示需要渲染的场景文件,传给 work.py; 参数 inputoss 表示 素材上传到 OSS 上的位置,也即1.4 中的 OSS 位置; 参数 outputoss 表示最终结果上传到 Oss 上的位置; 参数 frames 表示需要渲染的场景文件的帧数,传给 work.py;3ds MAX 不支持隔帧渲染,只能是连续帧,如1-10; 参数 retType 表示需要渲染渲染结果名称,传给 work.py,默认是 test.jpg,则最终得到test000.jpg 参数 clusterId 表示采用固定集群做渲染时,固定集群的Id。 4. 提交作业 根据以上示例文档,执行以下命令: python test.py -s Lighting-CB_Arnold_SSurface.max -i oss://bcs-test-sh/3dmaxdemo/Scenes/Lighting/ -o oss://bcs-test-sh/test/ -f 1-1 -t 123.jpg 示例运行结果: restulr picture

1934890530796658 2020-03-28 20:43:30 0 浏览量 回答数 0

回答

1、什么是 Vue.nextTick()? 定义:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。 所以就衍生出了这个获取更新后的 DOM 的 Vue 方法。所以放在 Vue.nextTick()回调函数中的执行的应该是会对 DOM 进行操作的 js 代码; 理解:nextTick(),是将回调函数延迟在下一次 dom 更新数据后调用,简单的理解是:当数据更新了,在 dom 中渲染后,自动执行该函数, 使用 this.$nextTick() methods:{ testClick:function(){ let that=this; that.testMsg="修改后的值"; that.$nextTick(function(){ console.log(that.$refs.aa.innerText); //输出:修改后的值 }); } } 注意:Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM, 2、什么时候需要用的 Vue.nextTick()?? 1、Vue 生命周期的 created()钩子函数进行的 DOM 操作一定要放在 Vue.nextTick()的回调函数中,原因是在 created()钩子函数执行的时候 DOM 其实并未进行任何渲染,而此时进行 DOM 操作无异于徒劳,所以此处一定要将 DOM 操作的 js 代码放进 Vue.nextTick()的回调函数中。与之对应的就是 mounted 钩子函数,因为该钩子函数执行时所有的 DOM 挂载已完成。 created(){ let that=this; that.$nextTick(function(){ //不使用this.$nextTick()方法会报错 that.$refs.aa.innerHTML="created中更改了按钮内容"; //写入到DOM元素 }); } 2、当项目中你想在改变 DOM 元素的数据后基于新的 dom 做点什么,对新 DOM 一系列的 js 操作都需要放进 Vue.nextTick()的回调函数中;通俗的理解是:更改数据后当你想立即使用 js 操作新的视图的时候需要使用它 {{testMsg}} 3、在使用某个第三方插件时 ,希望在 vue 生成的某些 dom 动态发生变化时重新应用该插件,也会用到该方法,这时候就需要在 $nextTick 的回调函数中执行重新应用插件的方法。 Vue.nextTick(callback) 使用原理: 原因是,Vue 是异步执行 dom 更新的,一旦观察到数据变化,Vue 就会开启一个队列,然后把在同一个事件循环 (event loop) 当中观察到数据变化的 watcher 推送进这个队列。如果这个 watcher 被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和 DOm 操作。而在下一个事件循环时,Vue 会清空队列,并进行必要的 DOM 更新。 当你设置 vm.someData = 'new value',DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的 DOM 更新。如果此时你想要根据更新的 DOM 状态去做某些事情,就会出现问题。。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。

问问小秘 2019-12-02 03:21:01 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 企业建站模板