webView 清除背景和<> 等特殊字符的自动转换

本文介绍如何使用Objective-C调整UIWebView中的HTML内容样式,包括去除滚动背景、改变字体颜色及大小等,并提供具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
   
    NSString *tempString = @"&lt;div&gt;sdfsdfsdf&lt;/div&gt"; //这种形式他会自动帮我们变成<>
    NSString *tempString2 = @"<div>sdfsdfsdf</div>"; //这种形式他会自动帮我们去掉<div>等。
    [self.myWebView loadHTMLString:tempString2 baseURL:nil];
    self.myWebView.backgroundColor = [UIColor clearColor];
    [self clearWebViewBackgroundWithColor];
    self.myWebView.opaque = NO;
}
- (void)clearWebViewBackgroundWithColor{//下面这个方法是去除滚动的时候的背景。
    NSLog(@"%d===",[[self.myWebView subviews]count]);
     NSLog(@"%d===",[[[[self.myWebView subviews]objectAtIndex:0]subviews]count]);
   
    for (UIView *view in [self.myWebView subviews]){
        if ([view isKindOfClass:[UIScrollView class]]){
            for (UIView *shadowView in view.subviews){
                // 上下滚动出边界时的黑色的图片 也就是拖拽后的上下阴影
                if ([shadowView isKindOfClass:[UIImageView class]]){
                    shadowView.hidden = YES;
                }
            }
        }
    }
}

 

 

 

 

改变UIwebView 的字体颜色和大小。

 

 NSString *tempString2 = @"<div>sdfsdfsdf</div>";
   
    NSString *jsString = [NSString stringWithFormat:@"<html> \n"
                          "<head> \n"
                          "<style type=\"text/css\"> \n"
                          "body {font-size: %d; font-family: \"%@\"; color: %@;font-weight:bold;}\n"
                          "</style> \n"
                          "</head> \n"
                          "<body>%@</body> \n"
                          "</html>", 33, @"Arail", @"red", tempString2];
    [self.myWebView loadHTMLString:jsString baseURL:nil];

<template> <view class="progress-container"> <!-- 外层刻度 --> <view class="scale-container"> <view v-for="(item, index) in 12" :key="index" class="scale-item" :style="{ transform: `rotate(${index * 30}deg)`, backgroundColor: progress >= 100 ? '#5BCEFF' : '#3B82F6' }" ></view> </view> <!-- 进度条 --> <view class="progress-wrapper"> <svg class="progress-svg" viewBox="0 0 100 100" > <!-- 背景圆环 --> <circle cx="50" cy="50" :r="radius" fill="none" stroke="#F2F7FF" :stroke-width="strokeWidth" /> <!-- 进度圆环 --> <circle cx="50" cy="50" :r="radius" fill="none" :stroke="progress >= 100 ? 'url(#gradientComplete)' : 'url(#gradientIncomplete)'" :stroke-width="strokeWidth" :stroke-dasharray="circumference" :stroke-dashoffset="dashOffset" stroke-linecap="round" transform="rotate(-90 50 50)" /> <!-- 渐变色定义 --> <defs> <linearGradient id="gradientIncomplete" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" stop-color="#F2F7FF" /> <stop offset="100%" stop-color="#3B82F6" /> </linearGradient> <linearGradient id="gradientComplete" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" stop-color="#5BCEFF" /> <stop offset="100%" stop-color="#4BFF75" /> </linearGradient> </defs> </svg> <!-- 中间内容 --> <view class="progress-content"> <slot></slot> </view> </view> </view> </template> <script setup> import { computed } from 'vue' const props = defineProps({ progress: { type: Number, default: 0, validator: value => value >= 0 && value <= 100 }, // 圆环半径(基于viewBox的百分比) radius: { type: Number, default: 40 }, // 圆环宽度(基于viewBox的百分比) strokeWidth: { type: Number, default: 5 } }) // 计算圆周长 const circumference = computed(() => 2 * Math.PI * props.radius) // 计算进度偏移量 const dashOffset = computed(() => { const progress = Math.min(Math.max(props.progress, 0), 100) return circumference.value * (1 - progress / 100) }) </script> <style lang="scss" scoped> .progress-container { position: relative; width: 300rpx; height: 300rpx; display: flex; justify-content: center; align-items: center; } .progress-wrapper { position: relative; width: 100%; height: 100%; } .progress-svg { width: 100%; height: 100%; transform: rotate(0deg); } .progress-content { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 60%; height: 60%; border-radius: 50%; background-color: white; display: flex; justify-content: center; align-items: center; flex-direction: column; } .scale-container { position: absolute; width: calc(100% + 20rpx); height: calc(100% + 20rpx); top: -10rpx; left: -10rpx; } .scale-item { position: absolute; width: 4rpx; height: 10rpx; top: 0; left: 50%; transform-origin: 50% 150rpx; border-radius: 2rpx; } </style> 帮我将这个组件转化为可以适配Android,ios,小程序,pc得uniapp vue3代码
06-08
<!-- pages/webview/webview.vue --> <template> <view class="webview-container"> <cover-view class="webview-wrapper"> <web-view :src="webviewPath" id="targetWebview"></web-view> </cover-view> <cover-view class="bottom-action-area"> <cover-view class="capture-btn" @click="captureWebview"> <cover-view class="btn-text">立即取证</cover-view> </cover-view> </cover-view> <!-- 预览组件 --> <cover-view v-if="showPreview" class="custom-preview"> <cover-view class="preview-header"> <cover-view class="title-container"> <cover-view class="preview-title">预览界面</cover-view> </cover-view> </cover-view> <cover-image :src="screenshotPath" class="preview-image" mode="aspectFit" @error="handleImageError" ></cover-image > <cover-view class="action-buttons"> <cover-view class="action-btn cancel-btn" @click="handleAction('放弃')">放弃</cover-view> <cover-view class="action-btn confirm-btn" @click="handleAction('固化')">固化</cover-view> </cover-view> <cover-view> </cover-view> </cover-view> </view> </template> <script setup lang="ts"> import { onLoad, onReady } from '@dcloudio/uni-app'; import html2canvas from 'html2canvas'; import { ref } from 'vue'; declare const plus: any; const webviewPath = ref(''); const ws = ref<any>(null); const screenshotPath = ref(''); const showPreview = ref(false); const platform = ref(''); const originalWebviewHeight = ref('auto'); const screenshotFilePath = ref(''); // 保存截图文件路径 const webviewContentHeight = ref(0); onLoad((options: any) => { if (options.url) { webviewPath.value = decodeURIComponent(options.url); } // 获取当前平台 const systemInfo = uni.getSystemInfoSync(); platform.value = systemInfo.platform; }); onReady(() => { const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; const currentWebview = currentPage.$getAppWebview(); setTimeout(() => { if (currentWebview.children().length > 0) { const wv = currentWebview.children()[0]; ws.value = wv; // originalWebviewHeight.value = wv.getStyle().height || 'auto'; wv.setStyle({ height: 'auto' }); setTimeout(() => { const webviewStyle = wv.getStyle(); // 保存网页实际高度(用于后续截图范围确认) webviewContentHeight.value = parseInt(webviewStyle.height) || 0; console.log('网页实际内容高度:', webviewContentHeight.value, 'px'); }, 2000); } }, 1000); }); const captureWebview = async () => { uni.showLoading({ title: '正在取证中...', mask: true }); if (!ws.value) { uni.showToast({ title: '网页未加载完成 请稍等重试', icon: 'none' }); uni.hideLoading(); return; } // 检查网页内容高度是否有效 if (webviewContentHeight.value === 0) { uni.showToast({ title: '网页内容未加载完全', icon: 'none' }); uni.hideLoading(); return; } // #ifdef APP-PLUS const bitmap = new plus.nativeObj.Bitmap('screenshot') // const fileName = `${Date.now()}.jpg` // const savePath = `_doc/${fileName}` const rand = Math.floor(Math.random() * 10000) const saveUrl = '_doc/' + rand + 'order.jpg' // 绘制页面截图 ws.value.draw(bitmap, () => { // 保存图片 bitmap.save( saveUrl, { format: 'jpg', quality: 90 }, (res:any) => { // 将本地路径转换为可以展示的路径 const previewPath = plus.io.convertLocalFileSystemURL(res.target) screenshotPath.value = previewPath screenshotFilePath.value = res.target; // 保存文件路径 console.log('截图保存成功,预览路径:', previewPath) // 延迟展示,确保加载完成 setTimeout(() => { showPreview.value = true uni.hideLoading(); }, 300) bitmap.clear() }, (err:any) => { console.error('保存失败:', err) uni.hideLoading(); uni.showToast({ title: '保存失败: ' + err.message, icon: 'none', }) bitmap.clear() } ) }, (err:any) => { console.error('截图失败:', err) uni.hideLoading(); uni.showToast({ title: '截图失败: ' + err.message, icon: 'none', }) }) // #endif // #ifdef APP-H5 html2canvas(document.querySelector('.webview-wrapper')).then((canvas) => { const dataUrl = canvas.toDataURL('image/jpeg') screenshotPath.value = dataUrl showPreview.value = true uni.hideLoading(); }).catch(err => { console.error('H5截图失败:', err) uni.hideLoading(); // H5失败时关闭加载提示 uni.showToast({ title: '截图失败', icon: 'none' }) }) // #endif } const closePreview = () => { showPreview.value = false; } const uploadEvidence = () => { plus.io.resolveLocalFileSystemURL(screenshotFilePath.value, (entry) => { console.log('文件存在,开始上传:', entry.name); // 继续执行上传逻辑 uni.showLoading({ title: '上传证据中...', mask: true }); // ... 原有上传代码 ... }, (err) => { console.error('文件不存在或路径错误:', err); uni.showToast({ title: '文件路径无效', icon: 'none' }); } ); uni.showLoading({ title: '上传证据中...', mask: true }); // #ifdef APP-PLUS // APP环境上传 uni.uploadFile({ url: 'http://192.168.1.80:1592/api/upload', filePath: screenshotFilePath.value, name: 'file', type: 'image', formData: { 'timestamp': Date.now() }, success: (uploadRes) => { uni.hideLoading(); try { const data = JSON.parse(uploadRes.data); if (data.success) { uni.showToast({ title: '证据上传成功', icon: 'none' }) } else { uni.showToast({ title: '上传失败', icon: 'none' }) } } catch (e) { uni.showToast({ title: '解析响应失败', icon: 'none' }) } // 3秒后关闭状态提示 setTimeout(() => { closePreview(); }, 3000); }, fail: (err) => { uni.hideLoading(); console.error('上传错误详情:', err); uni.showToast({ title: '网络错误'+ err.errMsg, icon: 'none' }) setTimeout(() => { }, 3000); } }); // #endif // #ifdef APP-H5 // H5环境上传 // if (!screenshotFilePath.value) { // uni.hideLoading(); // uni.showToast({ title: '文件路径无效', icon: 'none' }); // return; // } // 获取文件对象 // fetch(screenshotFilePath.value) // .then(res => res.blob()) // .then(blob => { // const formData = new FormData(); // formData.append('evidence', blob, `evidence-${Date.now()}.jpg`); // formData.append('timestamp', Date.now().toString()); // return fetch('http://192.168.1.80:1592/api/upload', { // method: 'POST', // body: formData // }); // }) // .then(response => response.json()) // .then(data => { // uni.hideLoading(); // if (data.success) { // uni.showToast({ title: '证据上传成功', icon: 'none' }); // } else { // uni.showToast({ title: '上传失败'+ data.message, icon: 'none' }); // } // setTimeout(() => { // closePreview(); // }, 3000); // }) // .catch(err => { // uni.hideLoading(); // uni.showToast({ title: '上传失败'+ err.message, icon: 'none' }) // setTimeout(() => { // }, 3000); // }); // #endif } const handleAction = (action: string) => { switch(action) { case '放弃': closePreview(); break; case '固化': uni.saveImageToPhotosAlbum({ filePath: screenshotPath.value, success: () => { uni.showToast({ title: '证据已固化保存' }); // 调用上传函数 uploadEvidence(); }, fail: (err) => { uni.showToast({ title: '保存失败: ' + err.errMsg, icon: 'none' }); } }); break; } } const handleImageError = (e: any) => { console.error('图片加载错误:', e); uni.showToast({ title: '图片加载错误', icon: 'none' }); } </script> <style> .webview-container { position: relative; width: 100%; height: 100vh; overflow: hidden; } .webview-wrapper { height: calc(100vh - 120rpx); width: 100%; overflow: hidden; } .bottom-action-area { position: fixed; bottom: 0; left: 0; right: 0; z-index: 100; background-color: #007aff; padding: 30rpx; padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); display: flex; justify-content: center; align-items: center; } .capture-btn { width: 100%; height: 90rpx; background-color: #007aff; border-radius: 45rpx; box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.2); display: flex; align-items: center; justify-content: center; } .btn-text { color: #ffffff; font-size: 32rpx; font-weight: 500; } /* 优化预览组件 */ .custom-preview { position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 9999; background-color: rgba(0, 0, 0, 0.9); display: flex; flex-direction: column; /* 垂直排列子元素 */ align-items: center; /* 关键修改:去掉顶部内边距,只保留底部内边距 */ padding: 0; box-sizing: border-box; } .preview-header { width: 100%; height: 250rpx; /* 增加高度 */ background-color: #007aff; color: #ffffff; font-size: 34rpx; /* 增大字体 */ font-weight: bold; display: flex; align-items: center; justify-content: center; /* 添加圆角效果 */ border-top-left-radius: 16rpx; border-top-right-radius: 16rpx; } .preview-title { color: #ffffff; /* 白色字体 */ font-size: 28rpx; /* 字体大小适配40rpx高度 */ font-weight: bold; line-height: 40rpx; /* 与容器高度一致,实现垂直居中 */ width: 100%; text-align: center; } .preview-image { width: 100%; height: 100%; object-fit: contain; border: 1rpx solid rgba(255, 255, 255, 0.1); border-radius: 8rpx; background-color: #f5f5f5; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.3); } .action-buttons { display: flex; width: 100%; /* 充满整个宽度 */ justify-content: space-between; padding: 30rpx 5%; /* 左右留5%间隙,上下30rpx内边距扩展背景区域 */ margin-top: auto; /* 借助flex布局推到最底部 */ background-color: #353336; /* 底部模块背景色 */ box-sizing: border-box; /* 确保padding不影响宽度计算 */ } .action-btn { flex: 1; height: 90rpx; border-radius: 12rpx; display: flex; align-items: center; justify-content: center; padding: 0; margin: 0 15rpx; border: none; color: #ffffff; /* 文字色适配深色背景 */ font-size: 34rpx; font-weight: 500; line-height: 1; } .cancel-btn { color: #ffffff; /* 文字颜色 */ font-size: 34rpx; font-weight: 500; /* 确保文字本身无偏移 */ line-height: 1; /* 清除行高影响 */ text-align: center; /* 辅助居中(冗余保障) */ background-color: #353336; } .confirm-btn { color: #ffffff; /* 文字颜色 */ font-size: 34rpx; font-weight: 500; /* 确保文字本身无偏移 */ line-height: 1; /* 清除行高影响 */ text-align: center; /* 辅助居中(冗余保障) */ background-color: #353336; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .bottom-action-img{ position: fixed; top: 100; left: 0; right: 0; z-index: 100; background-color: #007aff; padding: 30rpx; display: flex; justify-content: center; align-items: center; } .action-img{ width: 100%; height: 90rpx; background-color: #007aff; display: flex; } </style> 根据这个代码 将截图的内容 变成长截图
08-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值