鸿蒙学习实战之路-PDF背景添加与删除最佳实践

最近好多朋友问我:“西兰花啊,我想给PDF文档加背景,咋搞?有时候加了背景又想删掉,这能行吗?” 害,这问题我太熟了!今天我就手把手带你搞定PDF背景的添加和删除,从图片背景到颜色背景,全部给你安排得明明白白~

一、背景,核心接口有哪些?

PDF Kit提供了两个核心接口来处理背景:

接口名 功能描述
addBackground 插入PDF文档背景
removeBackground 删除PDF文档背景

这两个接口就是咱们今天要摆弄的"壁纸工具",用好了,PDF文档任你美化~

二、添加背景,让文档更美观

1. 基本用法

import { pdfService } from '@kit.PDFKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

@Entry
@Component
struct PdfBackgroundExample {
  private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
  private context = this.getUIContext().getHostContext() as Context;

  build() {
    Column() {
      // 添加背景
      Button('添加背景')
        .onClick(async () => {
          // 确保沙箱目录有input.pdf文档
          let filePath = this.context.filesDir + '/input.pdf';
          let loadResult = this.pdfDocument.loadDocument(filePath);
          
          if (loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
            // 创建背景信息对象
            let backgroundInfo: pdfService.BackgroundInfo = new pdfService.BackgroundInfo();
            
            // 设置背景图片路径
            backgroundInfo.imagePath = this.context.filesDir + '/img.jpg';
            
            // 设置背景颜色
            backgroundInfo.backgroundColor = 50;
            
            // 设置背景样式
            backgroundInfo.isOnTop = true;
            backgroundInfo.rotation = 45;
            backgroundInfo.scale = 0.5;
            backgroundInfo.opacity = 0.3;
            
            // 设置背景位置
            backgroundInfo.verticalAlignment = pdfService.BackgroundAlignment.BACKGROUND_ALIGNMENT_TOP;
            backgroundInfo.horizontalAlignment = pdfService.BackgroundAlignment.BACKGROUND_ALIGNMENT_LEFT;
            backgroundInfo.horizontalSpace = 1.0;
            backgroundInfo.verticalSpace = 1.0;
            
            // 添加背景到第1-2页,包括奇数页和偶数页
            this.pdfDocument.addBackground(backgroundInfo, 0, 2, true, true);
            
            // 保存文档
            let outPdfPath = this.context.filesDir + '/testAddBackground.pdf';
            let saveResult = this.pdfDocument.saveDocument(outPdfPath);
            
            console.log('添加背景结果:', saveResult ? '成功' : '失败');
          }
          
          // 释放资源
          this.pdfDocument.releaseDocument();
        })
    }
  }
}

2. 实际应用场景

在实际开发中,我们通常会根据不同的需求设置不同的背景:

// 根据文档类型设置不同的背景
function setupBackground(pdfDoc: pdfService.PdfDocument, docType: string) {
  let backgroundInfo: pdfService.BackgroundInfo = new pdfService.BackgroundInfo();
  
  // 基础设置
  backgroundInfo.opacity = 0.3;
  backgroundInfo.scale = 0.5;
  
  // 根据文档类型设置不同背景
  switch (docType) {
    case 'report':
      backgroundInfo.imagePath = '/path/to/report_background.jpg';
      break;
    case 'contract':
      backgroundInfo.backgroundColor = 200; // 浅灰色
      break;
    case 'certificate':
      backgroundInfo.imagePath = '/path/to/certificate_background.jpg';
      backgroundInfo.rotation = 0;
      backgroundInfo.scale = 1.0;
      break;
  }
  
  // 添加到所有页面
  let pageCount = pdfDoc.getPageCount();
  pdfDoc.addBackground(backgroundInfo, 0, pageCount, true, true);
}

三、删除背景,一键搞定

1. 基本用法

// 删除背景
Button('删除背景')
  .onClick(async () => {
    let filePath = this.context.filesDir + '/testAddBackground.pdf';
    let loadResult = this.pdfDocument.loadDocument(filePath);
    
    if (loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
      // 检查是否有背景
      if (this.pdfDocument.hasBackground()) {
        // 删除背景
        let removeResult = this.pdfDocument.removeBackground();
        
        if (removeResult) {
          // 保存文档
          let outPdfPath = this.context.filesDir + '/removeBackground.pdf';
          let saveResult = this.pdfDocument.saveDocument(outPdfPath);
          console.log('删除背景结果:', saveResult ? '成功' : '失败');
        } else {
          console.log('删除背景失败');
        }
      } else {
        console.log('文档没有背景');
      }
    }
    
    // 释放资源
    this.pdfDocument.releaseDocument();
  })

🥦 西兰花警告

  • 性能问题:addBackground方法属于耗时操作,需要遍历每一页添加背景,页面较多时一定要放到线程里处理,不然会阻塞UI线程!
  • 图片格式:添加图片背景时,要确保图片格式受支持(PNG、BMP、JPEG),不然会添加失败!
  • 资源释放:操作完文档一定要记得调用releaseDocument(),不然会内存泄漏!
  • 页面范围:添加背景时,要注意设置正确的页面范围,避免背景添加到不需要的页面!
  • 透明度设置:透明度设置要合理,太大会影响文档内容的可读性,太小则背景效果不明显!

🥦 西兰花小贴士

  • 批量处理:添加背景时,可以指定起始页和结束页,实现部分页面添加
  • 奇偶页不同:通过设置oddPages和evenPages参数,可以为奇数页和偶数页设置不同的背景
  • 线程处理:处理大量页面时,建议使用Worker线程,避免阻塞UI
  • 预览效果:添加背景前,最好先预览一下效果,避免反复修改
  • 样式统一:保持背景的样式与文档整体风格一致,增强专业性

四、常见问题与解决方案

1. 添加背景时应用卡死

问题:调用addBackground后,应用卡死不动

解决方案:这是因为添加背景是耗时操作,需要放到线程里处理:

// 正确写法
import { worker } from '@kit.WorkerKit';

// 创建Worker来处理耗时操作
async function addBackgroundInWorker(filePath: string) {
  return new Promise((resolve, reject) => {
    const backgroundWorker = worker.createWorker('backgroundWorker.ts');
    
    backgroundWorker.onmessage = (message) => {
      resolve(message);
      backgroundWorker.terminate();
    };
    
    backgroundWorker.onerror = (error) => {
      reject(error);
      backgroundWorker.terminate();
    };
    
    backgroundWorker.postMessage({ filePath });
  });
}

2. 添加图片背景时失败

问题:调用addBackground添加图片背景时,返回失败

解决方案:检查图片路径是否正确,图片格式是否受支持:

// 正确写法
let backgroundInfo: pdfService.BackgroundInfo = new pdfService.BackgroundInfo();
backgroundInfo.imagePath = this.context.filesDir + '/img.jpg'; // 确保图片存在且格式正确

3. 删除背景时返回false

问题:调用removeBackground时,返回false

解决方案:先检查文档是否有背景,再删除:

// 正确写法
if (this.pdfDocument.hasBackground()) {
  let removeResult = this.pdfDocument.removeBackground();
  if (removeResult) {
    // 保存文档
  }
}

五、完整代码示例

import { pdfService } from '@kit.PDFKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

@Entry
@Component
struct PdfBackgroundCompleteExample {
  private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
  private context = this.getUIContext().getHostContext() as Context;

  // 添加背景
  async addBackground() {
    try {
      let filePath = this.context.filesDir + '/input.pdf';
      let loadResult = this.pdfDocument.loadDocument(filePath);
      
      if (loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
        let backgroundInfo: pdfService.BackgroundInfo = new pdfService.BackgroundInfo();
        // 设置背景图片路径
        backgroundInfo.imagePath = this.context.filesDir + '/img.jpg';
        // 设置背景颜色
        backgroundInfo.backgroundColor = 50;
        // 设置背景样式
        backgroundInfo.isOnTop = true;
        backgroundInfo.rotation = 45;
        backgroundInfo.scale = 0.5;
        backgroundInfo.opacity = 0.3;
        // 设置背景位置
        backgroundInfo.verticalAlignment = pdfService.BackgroundAlignment.BACKGROUND_ALIGNMENT_TOP;
        backgroundInfo.horizontalAlignment = pdfService.BackgroundAlignment.BACKGROUND_ALIGNMENT_LEFT;
        backgroundInfo.horizontalSpace = 1.0;
        backgroundInfo.verticalSpace = 1.0;
        // 添加到第1-2页
        this.pdfDocument.addBackground(backgroundInfo, 0, 2, true, true);
        // 保存文档
        let outPdfPath = this.context.filesDir + '/withBackground.pdf';
        let saveResult = this.pdfDocument.saveDocument(outPdfPath);
        
        console.log('添加背景结果:', saveResult ? '成功' : '失败');
        return saveResult;
      } else {
        console.log('加载PDF失败');
        return false;
      }
    } catch (error) {
      console.error('添加背景时出错:', error);
      return false;
    } finally {
      this.pdfDocument.releaseDocument();
    }
  }

  // 删除背景
  async removeBackground() {
    try {
      let filePath = this.context.filesDir + '/withBackground.pdf';
      let loadResult = this.pdfDocument.loadDocument(filePath);
      
      if (loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
        // 检查是否有背景
        if (this.pdfDocument.hasBackground()) {
          // 删除背景
          let removeResult = this.pdfDocument.removeBackground();
          
          if (removeResult) {
            // 保存文档
            let outPdfPath = this.context.filesDir + '/withoutBackground.pdf';
            let saveResult = this.pdfDocument.saveDocument(outPdfPath);
            
            console.log('删除背景结果:', saveResult ? '成功' : '失败');
            return saveResult;
          } else {
            console.log('删除背景失败');
            return false;
          }
        } else {
          console.log('文档没有背景');
          return true;
        }
      } else {
        console.log('加载PDF失败');
        return false;
      }
    } catch (error) {
      console.error('删除背景时出错:', error);
      return false;
    } finally {
      this.pdfDocument.releaseDocument();
    }
  }

  build() {
    Column() {
      Button('添加背景')
        .margin(10)
        .onClick(async () => {
          let result = await this.addBackground();
          if (result) {
            console.log('添加背景成功');
          } else {
            console.log('添加背景失败');
          }
        })

      Button('删除背景')
        .margin(10)
        .onClick(async () => {
          let result = await this.removeBackground();
          if (result) {
            console.log('删除背景成功');
          } else {
            console.log('删除背景失败');
          }
        })
    }
    .padding(20)
  }
}

六、实际应用案例

案例1:文档美化工具

在文档美化工具中,我们可以为普通文档添加背景:

import { pdfService } from '@kit.PDFKit';
import { worker } from '@kit.WorkerKit';

@Entry
@Component
struct DocumentBeautifier {
  private context = this.getUIContext().getHostContext() as Context;

  // 批量添加背景
  async batchAddBackground(filePaths: string[]) {
    for (let filePath of filePaths) {
      console.log(`正在处理: ${filePath}`);
      
      // 使用Worker处理耗时操作
      await this.addBackgroundInWorker(filePath);
    }
    
    console.log('批量处理完成');
  }

  // 在Worker中处理
  async addBackgroundInWorker(filePath: string) {
    // 实现Worker处理逻辑
    // ...
  }

  build() {
    Column() {
      Button('批量添加背景')
        .onClick(async () => {
          // 假设这里获取了多个PDF文件路径
          let filePaths = [
            this.context.filesDir + '/doc1.pdf',
            this.context.filesDir + '/doc2.pdf',
            this.context.filesDir + '/doc3.pdf'
          ];
          
          await this.batchAddBackground(filePaths);
        })
    }
  }
}

案例2:证书生成器

在证书生成器中,我们可以为证书添加美观的背景:

import { pdfService } from '@kit.PDFKit';

@Entry
@Component
struct CertificateGenerator {
  private pdfDocument: pdfService.PdfDocument = new pdfService.PdfDocument();
  private context = this.getUIContext().getHostContext() as Context;

  // 生成证书
  async generateCertificate(name: string) {
    try {
      let filePath = this.context.filesDir + '/certificate_template.pdf';
      let loadResult = this.pdfDocument.loadDocument(filePath);
      
      if (loadResult === pdfService.ParseResult.PARSE_SUCCESS) {
        // 添加证书背景
        let backgroundInfo: pdfService.BackgroundInfo = new pdfService.BackgroundInfo();
        backgroundInfo.imagePath = this.context.filesDir + '/certificate_background.jpg';
        backgroundInfo.rotation = 0;
        backgroundInfo.scale = 1.0;
        backgroundInfo.opacity = 0.8;
        
        // 添加背景到所有页面
        let pageCount = this.pdfDocument.getPageCount();
        this.pdfDocument.addBackground(backgroundInfo, 0, pageCount, true, true);
        
        // 这里可以添加证书内容,如姓名、日期等
        // ...
        
        // 保存证书
        let outPdfPath = this.context.filesDir + `/certificate_${name}.pdf`;
        let saveResult = this.pdfDocument.saveDocument(outPdfPath);
        
        console.log('生成证书结果:', saveResult ? '成功' : '失败');
        return saveResult;
      } else {
        console.log('加载证书模板失败');
        return false;
      }
    } catch (error) {
      console.error('生成证书时出错:', error);
      return false;
    } finally {
      this.pdfDocument.releaseDocument();
    }
  }

  build() {
    Column() {
      Button('生成证书')
        .onClick(async () => {
          let result = await this.generateCertificate('张三');
          if (result) {
            console.log('生成证书成功');
          } else {
            console.log('生成证书失败');
          }
        })
    }
  }
}

七、实用资源推荐

📚 推荐资料


我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐