普通组件与web组件长截屏方案:原则是利用Scroll内的组件可以使用componentSnapshot完整的截屏
【普通组件长截屏】

import { componentSnapshot, promptAction } from @kit.ArkUI
import { common } from @kit.AbilityKit
import { photoAccessHelper } from @kit.MediaLibraryKit
import fs from @ohos.file.fs ;
import { image } from @kit.ImageKit ;
import { BusinessError } from @kit.BasicServicesKit ;
@Entry
@Component
struct Page37 {
@State lineHeight: number = 0 // 单行文本的高度
@State pageHeight: number = 0 // 每页的最大高度
@State totalContentHeight: number = 0 // 整个文本内容的高度
@State textContent: string = " " // 文本内容,默认一个空格是为了计算单行文本的高度
@State scrollOffset: number = 0 // 当前滚动偏移量
@State totalPages: number = 1 // 总页数
@State currentPage: number = 1 // 当前页数
scroller: Scroller = new Scroller() // 滚动条实例
resetMaxLineHeight() {
if (this.lineHeight > 0 && this.pageHeight > 0 && this.totalContentHeight > 0) {
this.pageHeight = (Math.floor(this.pageHeight / this.lineHeight)) * this.lineHeight
this.totalPages = Math.ceil(this.totalContentHeight / this.pageHeight) //向上取整得到总页数
}
}
build() {
Column() {
SaveButton().onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
if (result === SaveButtonOnClickResult.SUCCESS) {
const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
// 免去权限申请和权限请求等环节,获得临时授权,保存对应图片
let helper = photoAccessHelper.getPhotoAccessHelper(context);
try {
// onClick触发后5秒内通过createAsset接口创建图片文件,5秒后createAsset权限收回。
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, jpg );
// 使用uri打开文件,可以持续写入内容,写入过程不受时间限制
let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
componentSnapshot.get("aaaa").then((pixelMap) => {
let packOpts: image.PackingOption = { format: image/png , quality: 100 }
const imagePacker: image.ImagePacker = image.createImagePacker();
return imagePacker.packToFile(pixelMap, file.fd, packOpts).finally(() => {
imagePacker.release(); //释放
fs.close(file.fd);
promptAction.showToast({
message: 图片已保存至相册 ,
duration: 2000
});
});
})
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
}
} else {
promptAction.showToast({
message: 设置权限失败! ,
duration: 2000
});
}
})
Text( 第一章 )
.margin({ top: 10, bottom: 10 })
.backgroundColor(Color.Pink)
.width( 100% )
.textAlign(TextAlign.Center)
Column() {
Scroll(this.scroller) {
Column() {
Text(this.textContent)
.id( aaaa )
.backgroundColor(Color.Orange)
.fontSize(20)
.lineHeight(40)
.fontColor(Color.Black)// .textOverflow({ overflow: TextOverflow.Clip })
.margin({ top: this.scrollOffset })
.onAreaChange((oldArea: Area, newArea: Area) => {
if (this.lineHeight == 0 && newArea.height > 0) {
this.lineHeight = newArea.height as number
this.resetMaxLineHeight()
//添加数据测试
let str = ""
for (let i = 1; i <= 20; i++) {
str += ` ${i}、荣誉和耻辱,是荣辱观中的一对基本范畴,是指社会对人们行为褒贬评价以及人们对这种评价的自我感受。知荣辱,是人性的标志,是人区别于动物、人之为人的重大标准。`
}
this.textContent = str
return
}
if (this.totalContentHeight != newArea.height) {
console.info(`newArea.height:${newArea.height}`)
this.totalContentHeight = newArea.height as number
this.resetMaxLineHeight()
}
})
}.hitTestBehavior(HitTestMode.Block) //禁止滑动
}.scrollBar(BarState.Off)
.constraintSize({ maxHeight: this.pageHeight == 0 ? 1000 : this.pageHeight })
}
.width( 100% )
.layoutWeight(1)
.onAreaChange((oldArea: Area, newArea: Area) => {
if (this.pageHeight == 0 && newArea.height > 0) {
this.pageHeight = newArea.height as number
this.resetMaxLineHeight()
}
})
Row() {
Button( 上一页 ).onClick(() => {
if (this.currentPage == 1) {
promptAction.showToast({ message: "没有上一页了" })
return;
}
this.scrollOffset += this.pageHeight
this.currentPage--;
})
Text(`${this.currentPage}/${this.totalPages}`)
Button( 下一页 ).onClick(() => {
if (this.currentPage == this.totalPages) {
promptAction.showToast({ message: "没有下一页了" })
return;
}
this.scrollOffset -= this.pageHeight
this.currentPage++;
})
}.margin({ top: 10, bottom: 10 }).backgroundColor(Color.Pink).width( 100% ).justifyContent(FlexAlign.SpaceAround)
}
.width( 100% )
.height( 100% )
.backgroundColor(Color.Gray)
}
}
【web组件长截屏】

src/main/resources/rawfile/test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
//用于根据浏览器对 CSS.supports 和 env/constant 的支持情况,动态地调整视口元标签的内容,以达到最佳的页面显示效果。
var coverSupport = CSS in window && typeof CSS.supports === function && (CSS.supports( top: env(a) ) ||
CSS.supports( top: constant(a) ))
document.write(
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0 +
(coverSupport ? , viewport-fit=cover : ) + " /> )
</script>
<title></title>
<!--用于设置浏览器页签上显示的小图标 start-->
<!-- <link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" /> -->
<link rel="stylesheet" href="mycss.css" />
<link rel="icon" href="./static/favicon.ico" />
<!--用于设置浏览器页签上显示的小图标 end-->
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div>测试测试</div>
<div>测试测试</div>
<div>测试测试</div>
<div>测试测试</div>
<div>测试测试</div>
<div>测试测试</div>
<div>测试测试</div>
<div>测试测试</div>
<div>哈哈哈哈</div>
<div>哈哈哈哈</div>
<div>哈哈哈哈</div>
<div>哈哈哈哈</div>
<div>哈哈哈哈</div>
<div>哈哈哈哈</div>
<div>哈哈哈哈</div>
<div>哈哈哈哈</div>
<div>1111111</div>
<div>1111111</div>
<div>1111111</div>
<div>1111111</div>
<div>1111111</div>
<div>1111111</div>
<div>1111111</div>
<div>1111111</div>
<div>1111111</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>2222222</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>aaaaaaa</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>bbbbbbb</div>
<div>到底了</div>
<div id="webBottom"></div>
</body>
<script>
//Android禁止微信调整字体大小
(function() {
if (typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function") {
handleFontSize();
} else {
if (document.addEventListener) {
document.addEventListener("WeixinJSBridgeReady", handleFontSize, false);
} else if (document.attachEvent) {
document.attachEvent("WeixinJSBridgeReady", handleFontSize);
document.attachEvent("onWeixinJSBridgeReady", handleFontSize);
}
}
function handleFontSize() {
WeixinJSBridge.invoke( setFontSizeCallback , {
fontSize : 0
});
WeixinJSBridge.on( menu:setfont , function() {
WeixinJSBridge.invoke( setFontSizeCallback , {
fontSize : 0
});
});
}
})();
function setWebHeight() {
window.hm.setWebHeight(document.getElementById( webBottom ).offsetTop);
}
// 在文档加载完成后执行 setWebHeight 函数
window.onload = function() {
setWebHeight();
};
</script>
</html>
src/main/ets/pages/Page42.ets
import { webview } from @kit.ArkWeb ;
import web_webview from @ohos.web.webview ;
import dataPreferences from @ohos.data.preferences ;
import { common } from @kit.AbilityKit ;
import { photoAccessHelper } from @kit.MediaLibraryKit ;
import { componentSnapshot, promptAction } from @kit.ArkUI ;
import fs from @ohos.file.fs ;
import { image } from @kit.ImageKit ;
import { BusinessError } from @kit.BasicServicesKit ;
class WebService {
setWebHeight = (height: string) => {
console.info( web高度: , height);
getContext().eventHub.emit("设置web高度",height)
}
}
@Entry
@Component
struct Page42 {
controller: webview.WebviewController = new webview.WebviewController();
webService: WebService = new WebService( );
methodList: Array<string> = []
@State isShort: boolean = true
@State webHeight: number | undefined = undefined
aboutToAppear(): void {
this.methodList.splice(0) //清空原数组
console.info( ====this.testObjtest , JSON.stringify(this.webService))
Object.keys(this.webService).forEach((key) => {
this.methodList.push(key)
console.info( ====key , key)
});
getContext().eventHub.on("设置web高度",(height:number)=>{
this.webHeight = height
})
}
build() {
Scroll() {
Column() {
SaveButton().onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
if (result === SaveButtonOnClickResult.SUCCESS) {
const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
// 免去权限申请和权限请求等环节,获得临时授权,保存对应图片
let helper = photoAccessHelper.getPhotoAccessHelper(context);
try {
// onClick触发后5秒内通过createAsset接口创建图片文件,5秒后createAsset权限收回。
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, jpg );
// 使用uri打开文件,可以持续写入内容,写入过程不受时间限制
let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
componentSnapshot.get("aaaa").then((pixelMap) => {
let packOpts: image.PackingOption = { format: image/png , quality: 100 }
const imagePacker: image.ImagePacker = image.createImagePacker();
return imagePacker.packToFile(pixelMap, file.fd, packOpts).finally(() => {
imagePacker.release(); //释放
fs.close(file.fd);
promptAction.showToast({
message: 图片已保存至相册 ,
duration: 2000
});
});
})
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`Failed to save photo. Code is ${err.code}, message is ${err.message}`);
}
} else {
promptAction.showToast({
message: 设置权限失败! ,
duration: 2000
});
}
})
Text( 1234测试顶部 ).backgroundColor(Color.Red).width( 100% ).height( 800lpx )
Web({ src: $rawfile( test.html ), controller: this.controller, renderMode: RenderMode.SYNC_RENDER })
.width( 100% )
.height(this.webHeight)
.layoutMode(WebLayoutMode.FIT_CONTENT)
.javaScriptAccess(true)//设置是否允许执行JavaScript脚本,默认允许执行。
.mixedMode(MixedMode.All)//HTTP和HTTPS混合
.javaScriptProxy({
name: "hm",
object: this.webService,
methodList: this.methodList,
controller: this.controller,
}).id("aaaa")
Text( 测试底部 ).backgroundColor(Color.Blue).width( 100% ).height( 800lpx )
}
}.width( 100% ).height( 100% ).align(Alignment.Top)
}
}
© 版权声明
文章版权归作者所有,未经允许请勿转载。如内容涉嫌侵权,请在本页底部进入<联系我们>进行举报投诉!
THE END
















暂无评论内容