feat:table cell vertical align

pr675
Hufe921 3 years ago
parent e68c0bebc3
commit 665e2018aa

@ -129,4 +129,20 @@
.ce-contextmenu-merge-cancel-cell {
background-image: url(../../../assets/images/merge-cancel-cell.svg);
}
.ce-contextmenu-vertical-align {
background-image: url(../../../assets/images/vertical-align.svg);
}
.ce-contextmenu-vertical-align-top {
background-image: url(../../../assets/images/vertical-align-top.svg);
}
.ce-contextmenu-vertical-align-middle {
background-image: url(../../../assets/images/vertical-align-middle.svg);
}
.ce-contextmenu-vertical-align-bottom {
background-image: url(../../../assets/images/vertical-align-bottom.svg);
}

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M7 9h1V3H7zm.5 3L5 9h5zM2 13h11v1H2z" fill="#3D4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 152 B

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M8 12H7v3h1zm-.5-3l2.5 3H5zM7 3h1V0H7zm.5 3L5 3h5zM2 7h11v1H2z" fill="#3D4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 198 B

@ -0,0 +1 @@
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 8H7v6h1zm-.5-3L10 8H5zM2 3h11v1H2z" fill="#3D4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 153 B

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M2 13h12v1H2zm0-3h8v1H2zm0-3h12v1H2zm0-6h12v1H2zm0 3h8v1H2z" fill="#3d4757" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 195 B

@ -1,4 +1,4 @@
import { IElement, ImageDisplay, INavigateInfo } from '../..'
import { IElement, ImageDisplay, INavigateInfo, VerticalAlign } from '../..'
import { EditorMode, PageMode, PaperDirection } from '../../dataset/enum/Editor'
import { RowFlex } from '../../dataset/enum/Row'
import { IDrawImagePayload, IPainterOptions } from '../../interface/Draw'
@ -47,6 +47,7 @@ export class Command {
private static deleteTable: CommandAdapt['deleteTable']
private static mergeTableCell: CommandAdapt['mergeTableCell']
private static cancelMergeTableCell: CommandAdapt['cancelMergeTableCell']
private static tableTdVerticalAlign: CommandAdapt['tableTdVerticalAlign']
private static image: CommandAdapt['image']
private static hyperlink: CommandAdapt['hyperlink']
private static deleteHyperlink: CommandAdapt['deleteHyperlink']
@ -120,6 +121,7 @@ export class Command {
Command.deleteTable = adapt.deleteTable.bind(adapt)
Command.mergeTableCell = adapt.mergeTableCell.bind(adapt)
Command.cancelMergeTableCell = adapt.cancelMergeTableCell.bind(adapt)
Command.tableTdVerticalAlign = adapt.tableTdVerticalAlign.bind(adapt)
Command.image = adapt.image.bind(adapt)
Command.hyperlink = adapt.hyperlink.bind(adapt)
Command.deleteHyperlink = adapt.deleteHyperlink.bind(adapt)
@ -311,6 +313,10 @@ export class Command {
return Command.cancelMergeTableCell()
}
public executeTableTdVerticalAlign(payload: VerticalAlign) {
return Command.tableTdVerticalAlign(payload)
}
public executeHyperlink(payload: IElement) {
return Command.hyperlink(payload)
}

@ -6,6 +6,7 @@ import { EditorContext, EditorMode, PageMode, PaperDirection } from '../../datas
import { ElementType } from '../../dataset/enum/Element'
import { ElementStyleKey } from '../../dataset/enum/ElementStyle'
import { RowFlex } from '../../dataset/enum/Row'
import { VerticalAlign } from '../../dataset/enum/VerticalAlign'
import { IDrawImagePayload, IPainterOptions } from '../../interface/Draw'
import { IEditorOption, IEditorResult } from '../../interface/Editor'
import { IElement, IElementStyle } from '../../interface/Element'
@ -997,6 +998,30 @@ export class CommandAdapt {
this.tableTool.render(element, position[index!])
}
public tableTdVerticalAlign(payload: VerticalAlign) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const positionContext = this.position.getPositionContext()
if (!positionContext.isTable) return
const { index, trIndex, tdIndex } = positionContext
const originalElementList = this.draw.getOriginalElementList()
const element = originalElementList[index!]
const curTd = element?.trList?.[trIndex!]?.tdList?.[tdIndex!]
if (
!curTd
|| curTd.verticalAlign === payload
|| (!curTd.verticalAlign && payload === VerticalAlign.TOP)
) {
return
}
// 重设垂直对齐方式
curTd.verticalAlign = payload
const { endIndex } = this.range.getRange()
this.draw.render({
curIndex: endIndex
})
}
public hyperlink(payload: IElement) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return

@ -1,3 +1,4 @@
import { VerticalAlign } from '../../../dataset/enum/VerticalAlign'
import { IRegisterContextMenu } from '../../../interface/contextmenu/ContextMenu'
import { Command } from '../../command/Command'
@ -5,6 +6,39 @@ export const tableMenus: IRegisterContextMenu[] = [
{
isDivider: true
},
{
i18nPath: 'contextmenu.table.verticalAlign',
icon: 'vertical-align',
when: (payload) => {
return !payload.isReadonly && payload.isInTable
},
childMenus: [
{
i18nPath: 'contextmenu.table.verticalAlignTop',
icon: 'vertical-align-top',
when: () => true,
callback: (command: Command) => {
command.executeTableTdVerticalAlign(VerticalAlign.TOP)
}
},
{
i18nPath: 'contextmenu.table.verticalAlignMiddle',
icon: 'vertical-align-middle',
when: () => true,
callback: (command: Command) => {
command.executeTableTdVerticalAlign(VerticalAlign.MIDDLE)
}
},
{
i18nPath: 'contextmenu.table.verticalAlignBottom',
icon: 'vertical-align-bottom',
when: () => true,
callback: (command: Command) => {
command.executeTableTdVerticalAlign(VerticalAlign.BOTTOM)
}
}
]
},
{
i18nPath: 'contextmenu.table.insertRowCol',
icon: 'insert-row-col',

@ -35,7 +35,11 @@
"deleteCol": "Delete 1 col",
"deleteTable": "Delete table",
"mergeCell": "Merge cell",
"mergeCancelCell": "Cancel merge cell"
"mergeCancelCell": "Cancel merge cell",
"verticalAlign": "Vertical align",
"verticalAlignTop": "top",
"verticalAlignMiddle": "middle",
"verticalAlignBottom": "bottom"
}
},
"datePicker": {

@ -35,7 +35,11 @@
"deleteCol": "删除1列",
"deleteTable": "删除整个表格",
"mergeCell": "合并单元格",
"mergeCancelCell": "取消合并"
"mergeCancelCell": "取消合并",
"verticalAlign": "垂直对齐",
"verticalAlignTop": "顶端对齐",
"verticalAlignMiddle": "垂直居中",
"verticalAlignBottom": "底端对齐"
}
},
"datePicker": {

@ -1,4 +1,4 @@
import { ElementType, RowFlex } from '../..'
import { ElementType, RowFlex, VerticalAlign } from '../..'
import { ZERO } from '../../dataset/constant/Common'
import { ControlComponent, ImageDisplay } from '../../dataset/enum/Control'
import { IComputePageRowPositionPayload, IComputePageRowPositionResult } from '../../interface/Position'
@ -112,15 +112,34 @@ export class Position {
for (let d = 0; d < tr.tdList!.length; d++) {
const td = tr.tdList[d]
td.positionList = []
const rowList = td.rowList!
const drawRowResult = this.computePageRowPosition({
positionList: td.positionList,
rowList: td.rowList!,
rowList,
pageNo,
startIndex: 0,
startX: (td.x! + tdPadding) * scale + tablePreX,
startY: td.y! * scale + tablePreY,
innerWidth: (td.width! - tdGap) * scale
})
// 垂直对齐方式
if (
td.verticalAlign === VerticalAlign.MIDDLE
|| td.verticalAlign == VerticalAlign.BOTTOM
) {
const rowsHeight = rowList.reduce((pre, cur) => pre + cur.height, 0)
const blankHeight = td.height! - tdGap - rowsHeight
const offsetHeight = td.verticalAlign === VerticalAlign.MIDDLE ? blankHeight / 2 : blankHeight
if (Math.floor(offsetHeight) > 0) {
td.positionList.forEach(tdPosition => {
const { coordinate: { leftTop, leftBottom, rightBottom, rightTop } } = tdPosition
leftTop[1] += offsetHeight
leftBottom[1] += offsetHeight
rightBottom[1] += offsetHeight
rightTop[1] += offsetHeight
})
}
}
x = drawRowResult.x
y = drawRowResult.y
}

@ -0,0 +1,5 @@
export enum VerticalAlign {
TOP = 'top',
MIDDLE = 'middle',
BOTTOM = 'bottom'
}

@ -33,6 +33,7 @@ import { ICursorOption } from './interface/Cursor'
import { defaultCursorOption } from './dataset/constant/Cursor'
import { IPageNumber } from './interface/PageNumber'
import { defaultPageNumberOption } from './dataset/constant/PageNumber'
import { VerticalAlign } from './dataset/enum/VerticalAlign'
export default class Editor {
@ -161,6 +162,7 @@ export default class Editor {
export {
Editor,
RowFlex,
VerticalAlign,
EditorZone,
EditorMode,
ElementType,

@ -1,3 +1,4 @@
import { VerticalAlign } from '../../dataset/enum/VerticalAlign'
import { IElement, IElementPosition } from '../Element'
import { IRow } from '../Row'
@ -17,4 +18,5 @@ export interface ITd {
colIndex?: number;
rowList?: IRow[];
positionList?: IElementPosition[];
verticalAlign?: VerticalAlign;
}

@ -6,6 +6,7 @@ import { ZERO } from '../dataset/constant/Common'
import { defaultControlOption } from '../dataset/constant/Control'
import { EDITOR_ELEMENT_ZIP_ATTR } from '../dataset/constant/Element'
import { ControlComponent, ControlType } from '../dataset/enum/Control'
import { ITd } from '../interface/table/Td'
interface IFormatElementListOption {
isHandleFirstElement?: boolean;
@ -308,11 +309,15 @@ export function zipElementList(payload: IElement[]): IElement[] {
delete tr.id
for (let d = 0; d < tr.tdList.length; d++) {
const td = tr.tdList[d]
tr.tdList[d] = {
const zipTd: ITd = {
colspan: td.colspan,
rowspan: td.rowspan,
value: zipElementList(td.value)
}
if (td.verticalAlign) {
zipTd.verticalAlign = td.verticalAlign
}
tr.tdList[d] = zipTd
}
}
}

Loading…
Cancel
Save