当前位置: 首页 > news >正文

广州网站建设骏域网站企业网上注册登记系统

广州网站建设骏域网站,企业网上注册登记系统,建设什么网站比较好,建设网站需要了解什么简介 React-grid-layout 是一个基于 React 的网格布局库#xff0c;它可以帮助我们轻松地在网格中管理和排列组件。它提供了一个直观的 API#xff0c;可以通过配置网格的大小、列数和组件的位置来实现复杂的布局#xff0c;还支持对网格中组件的拖拽和重新排列。 实现 诉…简介 React-grid-layout 是一个基于 React 的网格布局库它可以帮助我们轻松地在网格中管理和排列组件。它提供了一个直观的 API可以通过配置网格的大小、列数和组件的位置来实现复杂的布局还支持对网格中组件的拖拽和重新排列。 实现 诉求 绘制编排之后可以根据配置对页面进行正确的绘制 拖拽支持位置调整拖拽之后调整对应配置参数 缩放支持大小调整缩放之后调整对应配置参数 自动调整当配置有错误、拖拽时有碰撞时进行自动调整布局空间的自动优化 示例 https://react-grid-layout.github.io/react-grid-layout/examples/0-showcase.html 使用方式 const layout [{ i: a, x: 0, y: 1, w: 1, h: 1, static: true },{ i: b, x: 1, y: 0, w: 3, h: 2 },{ i: c, x: 4, y: 0, w: 1, h: 2 }, ];GridLayoutlayouts{layout}margin{[10, 10]}containerPadding{[10,10]}cols12rowHeight150width1200style{{}} {layout.map((item) (div key{item.i} classNameitem-stylediv{item.i}/divdivxy{item.x}/{item.y}/divdivwh{item.w}/{item.h}/div/div))} /GridLayout绘制 容器 高度计算 const containerHeight () {// autoSize的情况下不计算容器高度 if (!this.props.autoSize) { return; }// 底部坐标 获取布局中yh的最大值即为容器的最大坐标h值 const nbRow bottom(this.state.layout); const containerPaddingY this.props.containerPadding ? this.props.containerPadding[1] : this.props.margin[1];// 计算包含margin/padding的真实高度 return ${nbRow * this.props.rowHeight (nbRow - 1) * this.props.margin[1] containerPaddingY * 2}px; }compact布局 如果直接安装上述的计算方式绘制可能由于配置的问题会带来页面的浪费。因此react-grid-layout会默认对纵向空间进行压缩以避免空间的浪费也支持设置为横向压缩或者不压缩。在压缩过程中很关键的一部分在于对模块间碰撞的处理。 function compact(layout, compactType, cols) {// 对静态模块不进行压缩const compareWith getStatics(layout); // 排序 horizontal verticalconst sorted sortLayoutItems(layout, compactType); const out Array(layout.length); for (let i 0, len sorted.length; i len; i) {let l cloneLayoutItem(sorted[i]);if (!l.static) {l compactItem(compareWith, l, compactType, cols, sorted);compareWith.push(l);}// 放回正确的位置out[layout.indexOf(sorted[i])] l;// 在处理冲突的时候设置flagl.moved false;}return out; }// 压缩方法 function compactItem(compareWith: Layout,l: LayoutItem,compactType: CompactType,cols: number,fullLayout: Layout ): LayoutItem {const compactV compactType vertical;const compactH compactType horizontal;if (compactV) {// 垂直方向压缩静态元素所需容器的高度 与 当前元素的纵向起始位置l.y Math.min(bottom(compareWith), l.y);while (l.y 0 !getFirstCollision(compareWith, l)) {l.y--;}} else if (compactH) {while (l.x 0 !getFirstCollision(compareWith, l)) {l.x--;}}// 处理碰撞let collides;while ((collides getFirstCollision(compareWith, l))) {if (compactH) {resolveCompactionCollision(fullLayout, l, collides.x collides.w, x);} else {resolveCompactionCollision(fullLayout, l, collides.y collides.h, y);}// 水平方向不超过最大值if (compactH l.x l.w cols) {l.x cols - l.w;l.y;}}// 对上述的y--,x--做容错处理确保没有负值l.y Math.max(l.y, 0);l.x Math.max(l.x, 0);return l; }function getFirstCollision(layout: Layout,layoutItem: LayoutItem ): ?LayoutItem {for (let i 0, len layout.length; i len; i) {// collides方法 // 当前节点 或者节点出现在另一个节点的上方下边界 其他节点的起始位置/下方/右侧/左侧if (collides(layout[i], layoutItem)) return layout[i];} }function resolveCompactionCollision(layout: Layout,item: LayoutItem,moveToCoord: number,axis: x | y ) {const sizeProp heightWidth[axis]; // x: w, y: hitem[axis] 1;const itemIndex layout.map(layoutItem {return layoutItem.i;}).indexOf(item.i);// 至少要加1个位置的情况下其下一个元素开始判断是否与元素碰撞for (let i itemIndex 1; i layout.length; i) {const otherItem layout[i];// 静态元素不能动if (otherItem.static) continue;// 如果在当前元素的下方的话 breakif (otherItem.y item.y item.h) break;if (collides(item, otherItem)) {resolveCompactionCollision(layout,otherItem,// moveToCoord想相当于新的ymoveToCoord item[sizeProp],axis);}}item[axis] moveToCoord; }看一下紧凑布局的实际效果 const layout [{ i: a, x: 0, y: 0, w: 5, h: 5 },{ i: b, x: 7, y: 6, w: 3, h: 2, minW: 2, maxW: 4, static: true },{ i: c, x: 0, y: 10, w: 12, h: 2 },{ i: d, x: 2, y: 16, w: 8, h: 2 },{ i: e, x: 7, y: 9, w: 3, h: 1 }]; // 高度 (16 8) * 60 23 * 10 2 * 10 1690compact调整之后 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7UCuxkBr-1693221682629)(https://tech-proxy.bytedance.net/tos/images/1693221360491_d79de77167d3c591075cdc27711f3ed8.png)] 看一下碰撞检测之后的处理结果 allowOverlap | preventCollision **allowOverlap 为true时**可以允许覆盖/重叠并且不会对布局做压缩处理。 **preventCollision为true时**阻止碰撞发生在拖拽/缩放时会有其作用 容器绘制 render() {const { className, style, isDroppable, innerRef } this.props;//样式合并const mergedClassName classNames(layoutClassName, className);const mergedStyle {height: this.containerHeight(),...style,};return (divref{innerRef}className{mergedClassName}style{mergedStyle}// 拖拽功能onDrop{isDroppable ? this.onDrop : noop}onDragLeave{isDroppable ? this.onDragLeave : noop}onDragEnter{isDroppable ? this.onDragEnter : noop}onDragOver{isDroppable ? this.onDragOver : noop}{React.Children.map(this.props.children, child this.processGridItem(child))}{isDroppable this.state.droppingDOMNode this.processGridItem(this.state.droppingDOMNode, true)}{this.placeholder()}/div);}GridItem GridItem containerWidth{width} cols{cols} margin{margin} containerPadding{containerPadding || margin} maxRows{maxRows} rowHeight{rowHeight} w{l.w} h{l.h} x{l.x} y{l.y} i{l.i} minH{l.minH} minW{l.minW} maxH{l.maxH} maxW{l.maxW} static{l.static} cancel{draggableCancel} handle{draggableHandle} // 拖拽onDragStop{this.onDragStop} onDragStart{this.onDragStart} onDrag{this.onDrag} isDraggable{draggable} // 缩放 onResizeStart{this.onResizeStart} onResize{this.onResize} onResizeStop{this.onResizeStop} isResizable{resizable} resizeHandles{resizeHandlesOptions} resizeHandle{resizeHandle} isBounded{bounded} useCSSTransforms{useCSSTransforms mounted} usePercentages{!mounted} transformScale{transformScale} droppingPosition{isDroppingItem ? droppingPosition : undefined} {child} /GridItem计算实际位置top/left/width/height) function calcGridItemPosition(positionParams,x,y,w,h,state ){const { margin, containerPadding, rowHeight } positionParams;// 计算列宽 (containerWidth - margin[0] * (cols - 1) - containerPadding[0] * 2) / colsconst colWidth calcGridColWidth(positionParams);const out {};// 如果gridItem正在缩放就采用缩放时state记录的宽高(width,height)。// 通过回调函数获取布局信息if (state state.resizing) {out.width Math.round(state.resizing.width);out.height Math.round(state.resizing.height);}// 反之基于网格单元计算else {// gridUnits, colOrRowSize, marginPx// Math.round(colOrRowSize * gridUnits Math.max(0, gridUnits - 1) * marginPx)// margin值计算会单独留一个margin在下方或者右侧out.width calcGridItemWHPx(w, colWidth, margin[0]);out.height calcGridItemWHPx(h, rowHeight, margin[1]);}// 如果gridItem正在拖拽就采用拖拽时state记录的位置(left,top)// 通过回调函数获取布局信息if (state state.dragging) {out.top Math.round(state.dragging.top);out.left Math.round(state.dragging.left);}// 反之基于网格单元计算else {out.top Math.round((rowHeight margin[1]) * y containerPadding[1]);out.left Math.round((colWidth margin[0]) * x containerPadding[0]);}return out; } // 计算列宽 function calcGridColWidth(positionParams: PositionParams): number {const { margin, containerPadding, containerWidth, cols } positionParams;return ((containerWidth - margin[0] * (cols - 1) - containerPadding[0] * 2) / cols); } // 计算宽高的实际值最后一个margin会留在当前网格的下面 function calcGridItemWHPx(gridUnits, colOrRowSize, marginPx){// 0 * Infinity NaN, which causes problems with resize contraintsif (!Number.isFinite(gridUnits)) return gridUnits;return Math.round(colOrRowSize * gridUnits Math.max(0, gridUnits - 1) * marginPx); }[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CQGZ37uY-1693221682630)(https://tech-proxy.bytedance.net/tos/images/1693221360608_b333c2cc2256a2207154e26e5bbea246.png)] 拖拽 布局拖拽处理 onDrag onDrag: (i: string, x: number, y: number, GridDragEvent) void (i,x,y,{ e, node }) {const { oldDragItem } this.state;let { layout } this.state;const { cols, allowOverlap, preventCollision } this.props;const l getLayoutItem(layout, i);if (!l) return;// Create placeholder (display only)const placeholder {w: l.w,h: l.h,x: l.x,y: l.y,placeholder: true,i: i};const isUserAction true;// 根据实时拖拽 生成布局layout moveElement(layout,l,x,y,isUserAction,preventCollision,compactType(this.props),cols,allowOverlap);this.props.onDrag(layout, oldDragItem, l, placeholder, e, node);this.setState({layout: allowOverlap? layout: compact(layout, compactType(this.props), cols),activeDrag: placeholder});};function moveElement(layout: Layout,l: LayoutItem,x: ?number,y: ?number,isUserAction: ?boolean,preventCollision: ?boolean,compactType: CompactType,cols: number,allowOverlap: ?boolean ): Layout {if (l.static l.isDraggable ! true) return layout;if (l.y y l.x x) return layout;log(Moving element ${l.i} to [${String(x)},${String(y)}] from [${l.x},${l.y}]);const oldX l.x;const oldY l.y;//只 修改 xy 更快速if (typeof x number) l.x x;if (typeof y number) l.y y;l.moved true;// 排序以便在发生碰撞的时候找最近碰撞的元素let sorted sortLayoutItems(layout, compactType);const movingUp compactType vertical typeof y number? oldY y: compactType horizontal typeof x number? oldX x: false;if (movingUp) sorted sorted.reverse();const collisions getAllCollisions(sorted, l);const hasCollisions collisions.length 0;if (hasCollisions allowOverlap) {// 允许覆盖时 不处理return cloneLayout(layout);} else if (hasCollisions preventCollision) {// 不允许碰撞的时候撤销本次拖拽log(Collision prevented on ${l.i}, reverting.);l.x oldX;l.y oldY;l.moved false;return layout;}//处理碰撞for (let i 0, len collisions.length; i len; i) {const collision collisions[i];log(Resolving collision between ${l.i} at [${l.x},${l.y}] and ${collision.i} at [${collision.x},${collision.y}]);if (collision.moved) continue;if (collision.static) {// 与静态元素碰撞的时候只能处理当前移动的元素layout moveElementAwayFromCollision(layout,collision,l,isUserAction,compactType,cols);} else {layout moveElementAwayFromCollision(layout,l,collision,isUserAction,compactType,cols);}}return layout; }function moveElementAwayFromCollision(layout: Layout,collidesWith: LayoutItem,itemToMove: LayoutItem,isUserAction: ?boolean,compactType: CompactType,cols: number ): Layout {const compactH compactType horizontal;const compactV compactType ! horizontal;const preventCollision collidesWith.static;if (isUserAction) {isUserAction false;// 构建元素 出现在碰撞元素的左上方const fakeItem: LayoutItem {x: compactH ? Math.max(collidesWith.x - itemToMove.w, 0) : itemToMove.x,y: compactV ? Math.max(collidesWith.y - itemToMove.h, 0) : itemToMove.y,w: itemToMove.w,h: itemToMove.h,i: -1};if (!getFirstCollision(layout, fakeItem)) {log(Doing reverse collision on ${itemToMove.i} up to [${fakeItem.x},${fakeItem.y}].);return moveElement(layout,itemToMove,compactH ? fakeItem.x : undefined,compactV ? fakeItem.y : undefined,isUserAction,preventCollision,compactType,cols);}}return moveElement(layout,itemToMove,compactH ? itemToMove.x 1 : undefined,compactV ? itemToMove.y 1 : undefined,isUserAction,preventCollision,compactType,cols); }元素拖拽处理 使用mixinDraggable函数依赖react-draggable中的DraggableCore为模块提供拖拽能力支持 onDrag onDrag: (Event, ReactDraggableCallbackData) void (e,{ node, deltaX, deltaY }) {const { onDrag } this.props;if (!onDrag) return;if (!this.state.dragging) {throw new Error(onDrag called before onDragStart.);}let top this.state.dragging.top deltaY;let left this.state.dragging.left deltaX;const { isBounded, i, w, h, containerWidth } this.props;const positionParams this.getPositionParams();// 不得超过边界if (isBounded) {const { offsetParent } node;if (offsetParent) {const { margin, rowHeight } this.props;const bottomBoundary offsetParent.clientHeight - calcGridItemWHPx(h, rowHeight, margin[1]);top clamp(top, 0, bottomBoundary);const colWidth calcGridColWidth(positionParams);const rightBoundary containerWidth - calcGridItemWHPx(w, colWidth, margin[0]);left clamp(left, 0, rightBoundary);}}const newPosition: PartialPosition { top, left };this.setState({ dragging: newPosition });// Call callback with this dataconst { x, y } calcXY(positionParams, top, left, w, h);return onDrag.call(this, i, x, y, {e,node,newPosition});};缩放 布局缩放处理 onResize onResize: (i: string, w: number, h: number, GridResizeEvent) void (i,w,h,{ e, node }) {const { layout, oldResizeItem } this.state;const { cols, preventCollision, allowOverlap } this.props;// 把缩放之后的新元素set到layout中cb单独处理不可碰撞时的场景const [newLayout, l] withLayoutItem(layout, i, l {let hasCollisions;if (preventCollision !allowOverlap) {const collisions getAllCollisions(layout, { ...l, w, h }).filter(layoutItem layoutItem.i ! l.i);hasCollisions collisions.length 0;if (hasCollisions) {// 只能向右下角伸缩因此取x,y 的最小值保证拖拽元素在碰撞let leastX Infinity,leastY Infinity;collisions.forEach(layoutItem {if (layoutItem.x l.x) leastX Math.min(leastX, layoutItem.x);if (layoutItem.y l.y) leastY Math.min(leastY, layoutItem.y);});if (Number.isFinite(leastX)) l.w leastX - l.x;if (Number.isFinite(leastY)) l.h leastY - l.y;}}if (!hasCollisions) {// Set new width and height.l.w w;l.h h;}return l;});// Shouldnt ever happen, but typechecking makes it necessaryif (!l) return;// Create placeholder element (display only)const placeholder {w: l.w,h: l.h,x: l.x,y: l.y,static: true,i: i};this.props.onResize(newLayout, oldResizeItem, l, placeholder, e, node);// Re-compact the newLayout and set the drag placeholder.this.setState({layout: allowOverlap? newLayout: compact(newLayout, compactType(this.props), cols),activeDrag: placeholder});}; 元素缩放处理 使用mixinResizable函数依赖react-resizable中的Resizable为模块提供缩放能力支持 onResizeHandler onResizeHandler(e: Event,{ node, size }: { node: HTMLElement, size: Position },handlerName: string // onResizeStart, onResize, onResizeStop): void {const handler this.props[handlerName];if (!handler) return;const { cols, x, y, i, maxH, minH } this.props;let { minW, maxW } this.props;// 获取新的宽高let { w, h } calcWH(this.getPositionParams(), // margin, maxRows, cols, rowHeightsize.width,size.height,x,y);// 保证宽度至少为1minW Math.max(minW, 1);// 最大宽度不应超过当前行剩余的宽度缩放 可以挤掉其右侧的模块但是无法对左侧的模块进行改变maxW Math.min(maxW, cols - x);// 获取在上下边界内的值w clamp(w, minW, maxW);h clamp(h, minH, maxH);this.setState({ resizing: handlerName onResizeStop ? null : size });handler.call(this, i, w, h, { e, node, size });}// px 转 格数 function calcWH(positionParams: PositionParams,width: number,height: number,x: number,y: number ): { w: number, h: number } {const { margin, maxRows, cols, rowHeight } positionParams;const colWidth calcGridColWidth(positionParams);let w Math.round((width margin[0]) / (colWidth margin[0]));let h Math.round((height margin[1]) / (rowHeight margin[1]));// 在其边界内取值w clamp(w, 0, cols - x);h clamp(h, 0, maxRows - y);return { w, h }; } ResponsiveGridLayout 响应式布局主要实现的是针对不同宽度的适配。值得注意的是如果一定不想给每一个breakpoint配置layout的话请一定给最大的那个breakpoint配置layout。 配置 breakpoints: ?Object {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}, cols: ?Object {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2},// 固定间隔或者响应式间隔 e.g.[10,10]| {lg: [10, 10], md: [10, 10], ...}. margin: [number, number] | {[breakpoint: $Keysbreakpoints]: [number, number]} containerPadding: [number, number] | {[breakpoint: $Keysbreakpoints]: [number, number]}// 由断点查找的 layouts 对象 e.g. {lg: Layout, md: Layout, ...} layouts: {[key: $Keysbreakpoints]: Layout}// 回调函数 onBreakpointChange: (newBreakpoint: string, newCols: number) void, onLayoutChange: (currentLayout: Layout, allLayouts: {[key: $Keysbreakpoints]: Layout}) void, // 页面宽度变化时的回调可以根据需要修改 layout 或者处理其他内容 onWidthChange: (containerWidth: number, margin: [number, number], cols: number, containerPadding: [number, number]) void; 流程 布局生成方法 function findOrGenerateResponsiveLayout(layouts: ResponsiveLayoutBreakpoint,breakpoints: BreakpointsBreakpoint,breakpoint: Breakpoint,lastBreakpoint: Breakpoint,cols: number,compactType: CompactType ): Layout {// 如果有提供对应配置的layout 直接使用if (layouts[breakpoint]) return cloneLayout(layouts[breakpoint]);// 另外生成let layout layouts[lastBreakpoint];const breakpointsSorted sortBreakpoints(breakpoints);const breakpointsAbove breakpointsSorted.slice(breakpointsSorted.indexOf(breakpoint));for (let i 0, len breakpointsAbove.length; i len; i) {const b breakpointsAbove[i];if (layouts[b]) {layout layouts[b];break;}}layout cloneLayout(layout || []);return compact(correctBounds(layout, { cols: cols }), compactType, cols); }总结 **性能好**200个模块 约268.8ms 独立的是否更新layout的判断机制 用 transform: translateY(-5px) 只是改变了视觉位置元素本身位置还是在 0px不改动 css 布局因为渲染行为大多数情况下在元素本身所以效率比 top left 要高 功能齐全 附 https://react-grid-layout.github.io/react-grid-layout/examples/0-showcase.html https://github.com/react-grid-layout/react-grid-layout/tree/master
http://www.dnsts.com.cn/news/15722.html

相关文章:

  • 网站建设主要包括哪些简单的app开发制作
  • 新郑做网站推广wordpress禁用emoji
  • qq空间网站是多少网站安装wordpress
  • 域控制网站访问自己的网站打不开
  • 文章类型的网站模版如何网站seo
  • 免费家具网站模板wordpress文章显示作者信息
  • 中山智能设备网站建设网站开发凭证做什么科目
  • 大学网站首页设计广东网页设计培训
  • 重庆怎么自己做网站网上做名片的网站
  • 找做cad彩拼的网站汕头h5建站模板
  • 百度云资源搜索网站建设网站的注意事项
  • 做a动漫视频在线观看网站原单手表网站
  • 图书网页设计网站免费模板素材网站
  • 企业网站内页设计模板php网站开发电子书
  • 温州网站的建设做网站手机端需要pc端的源代码吗
  • 网站规划的流程湖南网站模板建站
  • 泰和县城乡建设局网站网络营销推广方法包括哪些
  • 网站有后台更新不了开网店流程图文详解
  • 福州专业网站设计团队推广引流要怎么做比较好
  • 网站建设开发费用入什么科目佛山网站制作做多少钱
  • 青岛网站设计系统17网站一起做网店广州沙河
  • 二级目录 网站建设网站需要哪些编程
  • 自己怎么用h5做网站短视频营销成功案例
  • 做网站维护的人叫啥做网站页面
  • 温州建设网站公司装饰工程预算表
  • 国外开源代码网站网站移动字幕要怎么做
  • 网站备案幕布可以ps么虫虫管理wordpress软件
  • 东莞网站开发公司企业网站建设网
  • 仿站模板互联网基础知识入门
  • 免费手机h5模板网站模板下载小外包公司