HarmonyOS 鸿蒙Next svg 表格分享

发布于 1周前 作者 itying888 来自 鸿蒙OS

HarmonyOS 鸿蒙Next svg 表格分享

@Entry
@Component
struct Chart {
private data: number[] = [-30, -7, 70, -25, 500, 800]
private data2: number[] = [-10, 20, 100, 25, 50, 80]
private dates: string[] = [‘08/18’, ‘08/19’, ‘08/20’, ‘08/21’, ‘08/22’, ‘08/23’]
private YAxisFontSize: number = 10
private YAxisFontLineHeight: number = 12
private XAxisFontSize: number = 10
private XAxisFontLineHeight: number = 12
private XAxisLabelWidth: number = 30
@State chartWidth: number = 0
@State chartHeight: number = 0
@State showTooltip: boolean = false
@State tooltipX: number = 0
@State tooltipY: number = 0
@State tooltipContent: string = ‘’
@State activeIndex: number = 0

@Builder
Tooltip() {
if (this.showTooltip) {
Column() {
Text(this.tooltipContent)
.fontSize(12)
.fontColor(Color.White)
.padding(5)
}
.backgroundColor(Color.Black)
.borderRadius(5)
.position({ x: this.tooltipX, y: this.tooltipY })

}
}

@Builder
LineChart() {
Stack() {
Polyline({ width: ‘100%’, height: this.chartHeight })
.points([…this.getPoints()])
.fillOpacity(0)
.stroke(’#1880FF’)
.strokeWidth(1)
.strokeLineCap(LineCapStyle.Square)

// .linearGradient({
// direction: GradientDirection.Top, // 渐变方向
// repeating: true, // 渐变颜色是否重复
// colors: [[’#32328CFF’, 0.0], [’#FF328CFF’, 1]] // 数组末尾元素占比小于1时满足重复着色效果
// })
// .clip(new Path().commands(M ${vp2px(this.getPoints()?.[0]?.[0])} ${vp2px(this.chartHeight)} ${this.getPoints()<br> // .map(item =&gt;L ${vp2px(item[0])} ${vp2px(item[1])})<br> // .join(' ')} L ${vp2px(this.getPoints()?.slice(-1)?.[0]?.[0])} ${vp2px(this.chartHeight)} Z))
Polyline({ width: ‘100%’, height: this.chartHeight })
.points([…this.getPoints(this.data2)])
.fillOpacity(0)
.stroke(’#FFA53B’)
.strokeWidth(1)
.strokeLineCap(LineCapStyle.Square)
this.Tooltip()
if (this.showTooltip) {
Line()
.stroke(’#328CFF’)
.startPoint([0, 0])
.endPoint([0, this.chartHeight])
.position({ x: this.tooltipX, y: 0 })
}
}.padding({ top: this.YAxisFontLineHeight / 2 }).onTouch(
(event: TouchEvent) => {
console.log(JSON.stringify(event))
if (event.type === TouchType.Move || event.type === TouchType.Down) {
this.activeIndex = this.getClosestPointIndex(event.touches[0].x)
this.showTooltip = true
this.tooltipX = this.getPoints()[this.activeIndex][0]
this.tooltipY = this.getPoints()[this.activeIndex][1] - 30
this.tooltipContent = ${this.dates[this.activeIndex]}: ${this.data[this.activeIndex]}%
} else if (event.type === TouchType.Up) {
this.showTooltip = false
}
}
)
}

build() {
Column() {

Row() {
Column() {
ForEach(this.getYAxisLabels(), (label, index) => {
Text(label)
.fontSize(this.YAxisFontSize)
.lineHeight(this.YAxisFontLineHeight)
.textAlign(TextAlign.End)
})
}
.padding({ right: 6, bottom: this.YAxisFontLineHeight })
.height(‘100%’)
.alignItems(HorizontalAlign.End)
.justifyContent(FlexAlign.SpaceBetween)

Column() {
Stack() {
Column() {
ForEach(this.getYAxis(), (item, index) => {
Line()
.width(‘100%’)
.height(this.YAxisFontLineHeight)
.startPoint([0, this.YAxisFontLineHeight / 2])
.endPoint([this.chartWidth, this.YAxisFontLineHeight / 2])
.stroke($r(“app.color.l2”))
.strokeWidth(0.5)
.strokeDashArray([4])
})
}.height(‘100%’).justifyContent(FlexAlign.SpaceBetween)

Column() {
this.LineChart()
}
.width(this.chartWidth)
.animation({ duration: 1000, curve: Curve.Ease })
.clip(true)
.height(‘100%’)
}.layoutWeight(1).alignContent(Alignment.TopStart)
.onAreaChange((oldArea: Area, newArea: Area) => {
this.chartWidth = newArea.width as number
this.chartHeight = newArea.height as number - this.YAxisFontLineHeight
})

Row() {
ForEach(this.dates, (date) => {
Text(date)
.fontSize(this.XAxisFontSize)
.lineHeight(this.XAxisFontLineHeight)
.textAlign(TextAlign.Center)
.width(this.XAxisLabelWidth)
})
}.width(‘100%’).justifyContent(FlexAlign.SpaceBetween)
}.layoutWeight(1)

}.width(‘100%’).height(145)
}.padding(18)
}

getYAxis(): number[] {
const maxValue = Math.max(…this.data)
const minValue = Math.min(…this.data)
return this.calculateNiceScale(minValue, maxValue, 5).sort((a, b) => b - a)
}

getYAxisLabels(): string[] {
return this.getYAxis().map(value => ${value &gt; 0 ? '+' : ''}${Math.round(value)}%)
}

getPoints(data = this.data): Array<[number, number]> {
if (this.chartWidth === 0) return []
const rangeValues = this.getYAxis()
const maxValue = Math.max(…rangeValues)
const minValue = Math.min(…rangeValues)

const range = maxValue - minValue

const xWidth = (this.chartWidth - this.XAxisLabelWidth) / (this.data.length - 1)

return data.map((value, index) => [
index * xWidth + this.XAxisLabelWidth / 2,
this.chartHeight - ((value - minValue) / range * this.chartHeight)
])
}

getClosestPointIndex(x: number): number {
const points = this.getPoints()
let closestIndex = 0
let minDistance = Number.MAX_VALUE
points.forEach((point, index) => {
const distance = Math.abs(point[0] - x)
if (distance < minDistance) {
minDistance = distance
closestIndex = index
}
})
return closestIndex
}

niceNumber(range: number, round: boolean): number {
const exponent = Math.floor(Math.log10(range));
const fraction = range / Math.pow(10, exponent);
let niceFraction;

if (round) {
if (fraction < 1.5) niceFraction = 1;
else if (fraction < 3) niceFraction = 2;
else if (fraction < 7) niceFraction = 5;
else niceFraction = 10;
} else {
if (fraction <= 1) niceFraction = 1;
else if (fraction <= 2) niceFraction = 2;
else if (fraction <= 5) niceFraction = 5;
else niceFraction = 10;
}

return niceFraction * Math.pow(10, exponent);
}

calculateNiceScale(min: number, max: number, maxTicks: number = 5): number[] {
const range = this.niceNumber(max - min, false);
const tickSpacing = this.niceNumber(range / (maxTicks - 1), true);
const niceMin = Math.floor(min / tickSpacing) * tickSpacing;
const niceMax = Math.ceil(max / tickSpacing) * tickSpacing;

const ticks: number[] = [];
for (let tick = niceMin; tick <= niceMax; tick += tickSpacing) {
ticks.push(parseFloat(tick.toFixed(2)));
}

return ticks;
}
}

1 回复

针对您提到的HarmonyOS鸿蒙Next中SVG表格分享的问题,这里提供一些基本信息和可能的解决方案方向,但具体实现需依据您的开发环境和具体需求调整。

在HarmonyOS开发中,SVG(可缩放矢量图形)常用于展示图形和图标,因其支持无损缩放且文件体积小。若要实现SVG表格分享,首先需确保SVG文件已被正确加载到应用中。利用HarmonyOS提供的图形绘制API,您可以将SVG嵌入到表格中,形成SVG表格视图。

分享功能方面,HarmonyOS提供了丰富的数据分享接口,您可以通过Intent将数据(包括SVG表格)传递给其他应用。这里的关键在于如何将SVG表格数据序列化,以便在Intent中传递。一种常见做法是将SVG表格转换为图片格式(如PNG),再分享图片,因为直接分享SVG文件可能涉及兼容性问题。

此外,考虑使用HarmonyOS的Data Ability或FileProvider来管理共享数据的访问权限,确保数据安全。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。在那里,您可以获得更专业的技术支持和解决方案。

回到顶部