This commit is contained in:
巫翔 2024-11-19 16:59:54 +08:00
commit d2928bd43f
522 changed files with 243091 additions and 0 deletions

16
.browserslistrc Normal file
View File

@ -0,0 +1,16 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support
# You can see what browsers were selected by your queries by running:
# npx browserslist
Chrome >=79
ChromeAndroid >=79
Firefox >=70
Edge >=79
Safari >=14
iOS >=14

16
.editorconfig Normal file
View File

@ -0,0 +1,16 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false

46
.eslintrc.json Normal file
View File

@ -0,0 +1,46 @@
{
"root": true,
"ignorePatterns": ["projects/**/*"],
"overrides": [
{
"files": ["*.ts"],
"parserOptions": {
"project": ["tsconfig.json"],
"createDefaultProgram": true
},
"extends": [
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
"@angular-eslint/component-class-suffix": [
"error",
{
"suffixes": ["Page", "Component"]
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "app",
"style": "kebab-case"
}
],
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "app",
"style": "camelCase"
}
]
}
},
{
"files": ["*.html"],
"extends": ["plugin:@angular-eslint/template/recommended"],
"rules": {}
}
]
}

68
.gitignore vendored Normal file
View File

@ -0,0 +1,68 @@
# Specifies intentionally untracked files to ignore when using Git
# http://git-scm.com/docs/gitignore
*~
*.sw[mnpcod]
.tmp
*.tmp
*.tmp.*
UserInterfaceState.xcuserstate
$RECYCLE.BIN/
*.log
log.txt
/.sourcemaps
/.versions
/coverage
# Ionic
/.ionic
/www
/platforms
/plugins
# Compiled output
/dist
/tmp
/out-tsc
/bazel-out
# Node
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-project
*.sublime-workspace
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# Miscellaneous
/.angular
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
# System files
.DS_Store
Thumbs.db

5
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"recommendations": [
"ionic.ionic"
]
}

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"typescript.preferences.autoImportFileExcludePatterns": ["@ionic/angular/common", "@ionic/angular/standalone"]
}

3
README.md Normal file
View File

@ -0,0 +1,3 @@
### pdf js annotation 的 Demo
是一个 ionic 的项目,为了山核项目准备的。
在满足山核功能的基础上,精简了界面,处理了保存功能。

179
angular.json Normal file
View File

@ -0,0 +1,179 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"app": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "www",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
{
"glob": "**/*",
"input": "src/assets",
"output": "assets"
},
{
"glob": "**/*.svg",
"input": "node_modules/ionicons/dist/ionicons/svg",
"output": "./svg"
}
],
"styles": [
"src/global.scss",
"src/theme/variables.scss"
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
},
"ci": {
"progress": false
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "app:build:production"
},
"development": {
"buildTarget": "app:build:development"
},
"ci": {
"progress": false
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "app:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"inlineStyleLanguage": "scss",
"assets": [
{
"glob": "**/*",
"input": "src/assets",
"output": "assets"
},
{
"glob": "**/*.svg",
"input": "node_modules/ionicons/dist/ionicons/svg",
"output": "./svg"
}
],
"styles": [
"src/global.scss",
"src/theme/variables.scss"
],
"scripts": []
},
"configurations": {
"ci": {
"progress": false,
"watch": false
}
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
"src/**/*.ts",
"src/**/*.html"
]
}
},
"ionic-cordova-serve": {
"builder": "@ionic/cordova-builders:cordova-serve",
"options": {
"cordovaBuildTarget": "app:ionic-cordova-build",
"devServerTarget": "app:serve"
},
"configurations": {
"production": {
"cordovaBuildTarget": "app:ionic-cordova-build:production",
"devServerTarget": "app:serve:production"
}
}
},
"ionic-cordova-build": {
"builder": "@ionic/cordova-builders:cordova-build",
"options": {
"browserTarget": "app:build"
},
"configurations": {
"production": {
"browserTarget": "app:build:production"
}
}
}
}
}
},
"cli": {
"schematicCollections": [
"@ionic/angular-toolkit"
]
},
"schematics": {
"@ionic/angular-toolkit:component": {
"styleext": "scss"
},
"@ionic/angular-toolkit:page": {
"styleext": "scss"
}
}
}

101
config.xml Normal file
View File

@ -0,0 +1,101 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="cn.shuto.demo.pdfannotation" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>pdfannotation-demo</name>
<description>An awesome Ionic/Cordova app.</description>
<author email="hi@ionicframework.com" href="http://ionicframework.com/">Ionic Framework Team</author>
<content src="index.html" />
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<preference name="ScrollEnabled" value="false" />
<preference name="BackupWebStorage" value="none" />
<preference name="SplashMaintainAspectRatio" value="true" />
<preference name="FadeSplashScreenDuration" value="300" />
<preference name="SplashShowOnlyFirstTime" value="false" />
<preference name="SplashScreen" value="screen" />
<preference name="SplashScreenDelay" value="3000" />
<platform name="android">
<preference name="Scheme" value="http" />
<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application" xmlns:android="http://schemas.android.com/apk/res/android">
<application android:networkSecurityConfig="@xml/network_security_config" />
</edit-config>
<resource-file src="resources/android/xml/network_security_config.xml" target="app/src/main/res/xml/network_security_config.xml" />
<allow-intent href="market:*" />
<icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
<icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" />
<icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png" />
<icon density="xhdpi" src="resources/android/icon/drawable-xhdpi-icon.png" />
<icon density="xxhdpi" src="resources/android/icon/drawable-xxhdpi-icon.png" />
<icon density="xxxhdpi" src="resources/android/icon/drawable-xxxhdpi-icon.png" />
<splash density="land-ldpi" src="resources/android/splash/drawable-land-ldpi-screen.png" />
<splash density="land-mdpi" src="resources/android/splash/drawable-land-mdpi-screen.png" />
<splash density="land-hdpi" src="resources/android/splash/drawable-land-hdpi-screen.png" />
<splash density="land-xhdpi" src="resources/android/splash/drawable-land-xhdpi-screen.png" />
<splash density="land-xxhdpi" src="resources/android/splash/drawable-land-xxhdpi-screen.png" />
<splash density="land-xxxhdpi" src="resources/android/splash/drawable-land-xxxhdpi-screen.png" />
<splash density="port-ldpi" src="resources/android/splash/drawable-port-ldpi-screen.png" />
<splash density="port-mdpi" src="resources/android/splash/drawable-port-mdpi-screen.png" />
<splash density="port-hdpi" src="resources/android/splash/drawable-port-hdpi-screen.png" />
<splash density="port-xhdpi" src="resources/android/splash/drawable-port-xhdpi-screen.png" />
<splash density="port-xxhdpi" src="resources/android/splash/drawable-port-xxhdpi-screen.png" />
<splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png" />
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
<icon height="57" src="resources/ios/icon/icon.png" width="57" />
<icon height="114" src="resources/ios/icon/icon@2x.png" width="114" />
<icon height="29" src="resources/ios/icon/icon-small.png" width="29" />
<icon height="58" src="resources/ios/icon/icon-small@2x.png" width="58" />
<icon height="87" src="resources/ios/icon/icon-small@3x.png" width="87" />
<icon height="20" src="resources/ios/icon/icon-20.png" width="20" />
<icon height="40" src="resources/ios/icon/icon-20@2x.png" width="40" />
<icon height="60" src="resources/ios/icon/icon-20@3x.png" width="60" />
<icon height="48" src="resources/ios/icon/icon-24@2x.png" width="48" />
<icon height="55" src="resources/ios/icon/icon-27.5@2x.png" width="55" />
<icon height="29" src="resources/ios/icon/icon-29.png" width="29" />
<icon height="58" src="resources/ios/icon/icon-29@2x.png" width="58" />
<icon height="87" src="resources/ios/icon/icon-29@3x.png" width="87" />
<icon height="40" src="resources/ios/icon/icon-40.png" width="40" />
<icon height="80" src="resources/ios/icon/icon-40@2x.png" width="80" />
<icon height="120" src="resources/ios/icon/icon-40@3x.png" width="120" />
<icon height="88" src="resources/ios/icon/icon-44@2x.png" width="88" />
<icon height="50" src="resources/ios/icon/icon-50.png" width="50" />
<icon height="100" src="resources/ios/icon/icon-50@2x.png" width="100" />
<icon height="60" src="resources/ios/icon/icon-60.png" width="60" />
<icon height="120" src="resources/ios/icon/icon-60@2x.png" width="120" />
<icon height="180" src="resources/ios/icon/icon-60@3x.png" width="180" />
<icon height="72" src="resources/ios/icon/icon-72.png" width="72" />
<icon height="144" src="resources/ios/icon/icon-72@2x.png" width="144" />
<icon height="76" src="resources/ios/icon/icon-76.png" width="76" />
<icon height="152" src="resources/ios/icon/icon-76@2x.png" width="152" />
<icon height="167" src="resources/ios/icon/icon-83.5@2x.png" width="167" />
<icon height="172" src="resources/ios/icon/icon-86@2x.png" width="172" />
<icon height="196" src="resources/ios/icon/icon-98@2x.png" width="196" />
<icon height="1024" src="resources/ios/icon/icon-1024.png" width="1024" />
<splash height="480" src="resources/ios/splash/Default~iphone.png" width="320" />
<splash height="960" src="resources/ios/splash/Default@2x~iphone.png" width="640" />
<splash height="1024" src="resources/ios/splash/Default-Portrait~ipad.png" width="768" />
<splash height="768" src="resources/ios/splash/Default-Landscape~ipad.png" width="1024" />
<splash height="1125" src="resources/ios/splash/Default-Landscape-2436h.png" width="2436" />
<splash height="1242" src="resources/ios/splash/Default-Landscape-736h.png" width="2208" />
<splash height="2048" src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536" />
<splash height="1536" src="resources/ios/splash/Default-Landscape@2x~ipad.png" width="2048" />
<splash height="2732" src="resources/ios/splash/Default-Portrait@~ipadpro.png" width="2048" />
<splash height="2048" src="resources/ios/splash/Default-Landscape@~ipadpro.png" width="2732" />
<splash height="1136" src="resources/ios/splash/Default-568h@2x~iphone.png" width="640" />
<splash height="1334" src="resources/ios/splash/Default-667h.png" width="750" />
<splash height="2208" src="resources/ios/splash/Default-736h.png" width="1242" />
<splash height="2436" src="resources/ios/splash/Default-2436h.png" width="1125" />
<splash height="2732" src="resources/ios/splash/Default@2x~universal~anyany.png" width="2732" />
</platform>
<plugin name="cordova-plugin-statusbar" spec="2.4.2" />
<plugin name="cordova-plugin-device" spec="2.0.2" />
<plugin name="cordova-plugin-splashscreen" spec="5.0.2" />
<plugin name="cordova-plugin-ionic-webview" spec="^5.0.0" />
<plugin name="cordova-plugin-ionic-keyboard" spec="^2.0.5" />
</widget>

7
ionic.config.json Normal file
View File

@ -0,0 +1,7 @@
{
"name": "pdfannotation-demo",
"integrations": {
"cordova": {}
},
"type": "angular"
}

44
karma.conf.js Normal file
View File

@ -0,0 +1,44 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, './coverage/app'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
]
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};

15829
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

77
package.json Normal file
View File

@ -0,0 +1,77 @@
{
"name": "pdfannotation-demo",
"version": "0.0.1",
"author": "Ionic Framework",
"homepage": "https://ionicframework.com/",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"lint": "ng lint"
},
"private": true,
"dependencies": {
"@angular/animations": "^17.0.2",
"@angular/common": "^17.0.2",
"@angular/compiler": "^17.0.2",
"@angular/core": "^17.0.2",
"@angular/forms": "^17.0.2",
"@angular/platform-browser": "^17.0.2",
"@angular/platform-browser-dynamic": "^17.0.2",
"@angular/router": "^17.0.2",
"@ionic/angular": "^7.0.0",
"@ionic/cordova-builders": "^11.0.0",
"ionicons": "^7.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.0.0",
"@angular-eslint/builder": "^17.0.0",
"@angular-eslint/eslint-plugin": "^17.0.0",
"@angular-eslint/eslint-plugin-template": "^17.0.0",
"@angular-eslint/schematics": "^17.0.0",
"@angular-eslint/template-parser": "^17.0.0",
"@angular/cli": "^17.0.0",
"@angular/compiler-cli": "^17.0.2",
"@angular/language-service": "^17.0.2",
"@ionic/angular-toolkit": "^11.0.1",
"@types/jasmine": "~5.1.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"cordova-android": "^12.0.1",
"cordova-plugin-device": "2.0.2",
"cordova-plugin-ionic-keyboard": "^2.0.5",
"cordova-plugin-ionic-webview": "^5.0.0",
"cordova-plugin-splashscreen": "5.0.2",
"cordova-plugin-statusbar": "^2.4.2",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsdoc": "^48.2.1",
"eslint-plugin-prefer-arrow": "1.2.2",
"jasmine-core": "~5.1.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.2.2"
},
"description": "An Ionic project",
"cordova": {
"plugins": {
"cordova-plugin-statusbar": {},
"cordova-plugin-device": {},
"cordova-plugin-splashscreen": {},
"cordova-plugin-ionic-webview": {},
"cordova-plugin-ionic-keyboard": {}
},
"platforms": [
"android"
]
}
}

8
resources/README.md Normal file
View File

@ -0,0 +1,8 @@
These are Cordova resources. You can replace icon.png and splash.png and run
`ionic cordova resources` to generate custom icons and splash screens for your
app. See `ionic cordova resources --help` for details.
Cordova reference documentation:
- Icons: https://cordova.apache.org/docs/en/latest/config_ref/images.html
- Splash Screens: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-splashscreen/

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">localhost</domain>
</domain-config>
</network-security-config>

BIN
resources/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
resources/ios/icon/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
resources/splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View File

@ -0,0 +1,22 @@
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: 'home',
loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)
},
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules, useHash: false })
],
exports: [RouterModule]
})
export class AppRoutingModule { }

View File

@ -0,0 +1,3 @@
<ion-app>
<ion-router-outlet></ion-router-outlet>
</ion-app>

View File

View File

@ -0,0 +1,21 @@
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
});

10
src/app/app.component.ts Normal file
View File

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss'],
})
export class AppComponent {
constructor() {}
}

16
src/app/app.module.ts Normal file
View File

@ -0,0 +1,16 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
bootstrap: [AppComponent],
})
export class AppModule {}

View File

@ -0,0 +1,16 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomePage } from './home.page';
const routes: Routes = [
{
path: '',
component: HomePage,
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class HomePageRoutingModule {}

View File

@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';
import { FormsModule } from '@angular/forms';
import { HomePage } from './home.page';
import { HomePageRoutingModule } from './home-routing.module';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
HomePageRoutingModule
],
declarations: [HomePage]
})
export class HomePageModule {}

View File

@ -0,0 +1,17 @@
<ion-header [translucent]="true">
<ion-toolbar>
<ion-title>
PDF标注 Demo
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true" scroll-y="false">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">PDF标注 Demo</ion-title>
</ion-toolbar>
</ion-header>
<iframe id='my-pdfjs-iframe' class='sticky-container' src="/assets/pdf-annotation/web/viewer.html?file=tutorial.pdf&user=shuto" frameborder="0" width="100%" height="100%"></iframe>
</ion-content>

View File

@ -0,0 +1,27 @@
#container {
text-align: center;
position: absolute;
left: 0;
right: 0;
top: 50%;
transform: translateY(-50%);
}
#container strong {
font-size: 20px;
line-height: 26px;
}
#container p {
font-size: 16px;
line-height: 22px;
color: #8c8c8c;
margin: 0;
}
#container a {
text-decoration: none;
}

View File

@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { HomePage } from './home.page';
describe('HomePage', () => {
let component: HomePage;
let fixture: ComponentFixture<HomePage>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [HomePage],
imports: [IonicModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(HomePage);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

16
src/app/home/home.page.ts Normal file
View File

@ -0,0 +1,16 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
constructor() {}
}
window.addEventListener("message", function(event: any){
console.log(event);
}, false);

BIN
src/assets/icon/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,829 @@
var post_to_parent = false;
var shiftKeyPressed = false;
// tips_language决定了操作提示语
var tips_language = 'zh-cn';
// var tips_language = 'en';
var first_load = true;
var default_show_annotation_list = false; //控制右侧列表是否默认显示
if (window.screen.availWidth <= 650) {
default_show_annotation_list = false;
}
var last_connect_id = '-1';
var run_in_angular=true;
var select_link_type='url'; //超链接类型
var current_link_annotation_item=null; //当前批注对象
var is_hyper_link_highlight=false; //是否高亮
var is_hyper_edit=false; //是否高亮
var hyper_open_page=1;
var hyper_open_file=false;
var show_state = {}; //是否默认显示页面的批注列表
var add_water_mark = false; //是否添加水印
var show_my_menu = false; //显示颜色控制面板
var fold_my_munu=false;
var show_setting_menu = false; //显示配置面板
var changed_number_value = false; //修改颜色面板的内容
var onload_record_history = true; //加载时保存一次历史记录
var object_modified = false; //对象是否被编辑
// var add_annotation_list_title=true; //保留批注的表头按钮
var add_annotation_list_title=false; //保留批注的表头按钮
//是否默认显示批注
var hidden_open = '';
var hidden_close = '';
if (default_show_annotation_list == false) {
hidden_open = "hidden='true'";
} else {
hidden_close = "hidden='true'";
}
var default_show_onepage_annotation_list = false; //控制右侧列表每页批注是否默认展开
var hidden_container = '';
if (default_show_onepage_annotation_list == false) {
hidden_container = "hidden='true'";
hidden_open = "hidden='true'";
hidden_close = "";
} else {
hidden_close = "hidden='true'";
hidden_open = "";
}
var defult_left = 0;
var defult_top = 0;
var left_top_offset = 30;
//默认在视图上的显示比例
var show_scale_value = 1;
//下划线宽度和画笔宽度
var default_underline_width = 1;
var default_brush_width = 15;
var default_arrow_width = 3; //箭头粗细
//橡皮擦的默认大小
var default_eraser_brush_width = 30;
var default_text_size = 30;
//待提取的pdf页面列表
var extract_page_numbers = [];
var default_brush_opacity=100;
var default_fill_color_opacity = 30; //填充色不透明度
var default_border_color_opacity = 100; //边框色不透明度
//各类批注的的颜色
var default_border_color = "rgba(17, 153,158,1)";
var default_text_color = "rgba(17, 153,158,1)";
var default_fill_color = 'rgba(255, 237, 0,0.30)';
var default_hyperlink_fill_color = 'rgba(0,129,255,0.3)';
var default_stamp_color = "#0081FF";
var default_brush_color = '#E60000';
// var default_brush_decimate = 10; //画笔拐角流畅度
var default_brush_decimate = 0; //画笔拐角流畅度
var default_screenshot_rect_fill_color = 'rgba(236, 240, 241,0.5)';
var default_screenshot_rect_background_color = "rgba(17, 153,158,1)";
var default_screenshot_rect_text_color = 'rgba(255, 255, 255,1)';
var default_transparency_color = 'rgba(255, 255, 255,0)';
var default_highlight_color = 'rgba(255, 237, 0,1)';
var default_hyper_highlight_color='rgba(0,129,255,1)';
var default_underline_color = 'rgba(57, 181, 74,1)';
var defult_top = 0;
var defult_screen_shot_top = 30;
var default_eraser_color = "#0081FF";
var default_text;
var default_idcard_stamp;
var default_triangle;
var default_line;
var default_check_left_line;
var default_check_right_line;
var default_rectangle;
var default_straight_line;
var default_screenshot_text;
var default_screenshot_rectangle;
var default_circle;
var default_fill_opacity;
//设置默认批注对象
function setDefaultAnnotations() {
//default annotation object 默认批注对象
default_text = {
left: defult_left,
top: defult_top,
fill: default_text_color,
fontSize: default_text_size,
selectable: true,
id: 'id',
};
//身份印章配置,包括颜色,文字大小等
default_idcard_stamp = {
left: defult_left,
top: defult_top,
fill: default_stamp_color,
textAlign: 'center',
fontSize: 25,
selectable: true,
padding: 2,
my_type:'idcard_stamp_text',
};
default_triangle = {
width: 30,
height: 40,
fill: default_border_color,
left: 200 + left_top_offset,
top: 0 + left_top_offset,
angle: 90,
};
default_line = {
left: 0 + left_top_offset,
top: 13 + left_top_offset,
strokeWidth: 4,
stroke: default_border_color,
};
//对勾预制函数,由左右两条线构成
var default_check_width = 12;
default_check_left_line = {
left: 66 + default_check_width / 2 + left_top_offset,
top: 54 + default_check_width + left_top_offset,
angle: 67,
strokeWidth: default_check_width,
stroke: default_stamp_color,
};
default_check_right_line = {
left: 210 + default_check_width / 4 + left_top_offset,
top: 10 + default_check_width + left_top_offset,
angle: 135,
strokeWidth: default_check_width,
stroke: default_stamp_color,
};
default_rectangle = {
left: defult_left,
top: defult_top,
width: 300,
height: 300,
fill: default_fill_color,
stroke: default_border_color,
strokeSize: 1,
id: 'id',
};
// let line1 = new fabric.Line([lineleft, lineheight, lineleft,
// 0], { //终止位置线长起始位置top这里是从项目中截下来的我用了变量代替你要用的话lineheight和lineleft用自己的变量或者数字代替。如果两个终止位置和起始位置的数值一样那么这个线条会垂直这个应该很好理解。
// fill: '#5E2300', //填充颜色
// stroke: '#5E2300', //笔触颜色
// strokeWidth: 2, //笔触宽度
// hasControls: false, //选中时是否可以放大缩小
// hasRotatingPoint: false, //选中时是否可以旋转
// hasBorders: false, //选中时是否有边框
// transparentCorners: true,
// perPixelTargetFind: true, //默认false。当设置为true对象的检测会以像互点为基础而不是以边界的盒模型为基础。
// selectable: true, //是否可被选中
// lockMovementX: true, //X轴是否可被移动(true为不可因为前缀是lock)
// lockMovementY: true, //Y轴是否可被移动(true为不可因为前缀是lock)
// });
default_straight_line
= { //终止位置线长起始位置top这里是从项目中截下来的我用了变量代替你要用的话lineheight和lineleft用自己的变量或者数字代替。如果两个终止位置和起始位置的数值一样那么这个线条会垂直这个应该很好理解。
fill: default_border_color, //填充颜色
stroke: default_border_color, //笔触颜色
strokeWidth: 3, //笔触宽度
hasControls: true, //选中时是否可以放大缩小
hasRotatingPoint: true, //选中时是否可以旋转
hasBorders: true, //选中时是否有边框
selectable: true, //是否可被选中
};
//截屏批注
default_screenshot_text = {
left: defult_left,
top: defult_top,
fill: default_screenshot_rect_text_color,
backgroundColor: default_screenshot_rect_background_color,
fontSize: 25,
strokeWidth: 5,
underline: true,
selectable: true,
id: 'id',
lockRotation: true,
};
default_screenshot_rectangle = {
left: defult_left,
top: defult_screen_shot_top,
width: 300,
height: 300,
fill: default_screenshot_rect_fill_color,
stroke: default_fill_color,
lockRotation: true,
strokeSize: 1,
id: 'id',
lockRotation: true,
};
default_circle = {
left: defult_left,
top: defult_top,
radius: 200,
fill: default_fill_color,
stroke: default_border_color,
strokeSize: 1,
id: 'id',
};
}
//create color control panel 创建颜色控制面板
function setColorControl() {
if (isIE11()){
setColorControlForIE();
return;
}
var my_menu_node = document.getElementById('my-menu');
my_menu_node.innerHTML = ''; //clear 清空所有子元素
var buttons_text = {
'zh-cn': [
'<div title="关闭" onclick="hiddenMenu()"><label>关闭/close</label><i class="fa fa-times-circle" style="font-size: 15px;" aria-hidden="true"></i></div>',
'<div id="fold_or_open_div" title="折叠或展开面板" onclick="foldOrOpenMenu()"><label>折叠/展开面板</label><i class="fa fa-window-restore" style="font-size: 15px;margin-left:10px;" aria-hidden="true"></i></div>',
'<div onclick="clickColorInput(this)" title="点击色块修改颜色"><label>填充色</label><input type="color" value="#000000" id="fill"></div>',
'<div onclick="clickColorInput(this)" title="点击色块修改颜色"><label>边框色</label><input type="color" value="#000000" id="stroke"></div>',
'<div onclick="clickColorInput(this)" title="点击色块修改颜色"><label>背景色</label><input type="color" value="#000000" id="backgroundColor"></div>',
'<div title="拖动进度条调整"><label style="margin-right: 20px;">边框粗细</label><input type="range" style="width: 80px;" id="strokeWidth" value="1" min="0" max="20" step="0.5"></div>',
'<div title="拖动进度条调整"><label style="margin-right: 20px;">不透明度</label><input type="range" style="width: 80px;" id="opacity" value="100" min="1" max="100" step="1"></div>',
'<div hidden=true id="ff-panel-screenshot" onclick="screenShotEl()" title="截取当前区域"><label>截图当前区域</label><i class="fa fa-camera" style="font-size: 15px;" aria-hidden="true"></i></div>',
'<div onclick="delEl()" title="删除对象"><label>删除</label><i class="fa fa-trash" style="font-size: 15px;" aria-hidden="true"></i></div>',
],
'en': [
'<div title="Close" onclick="hiddenMenu()"><label>Close</label><i class="fa fa-times-circle" style="font-size: 15px;" aria-hidden="true"></i></div>',
'<div id="fold_or_open_div" title="fold or open panel" onclick="foldOrOpenMenu()"><label>Fold/Open Panel</label><i class="fa fa-window-restore" style="font-size: 15px;" aria-hidden="true"></i></div>',
'<div onclick="clickColorInput(this)" title="click to select color"><label>FillColor</label><input type="color" value="#000000" id="fill"></div>',
'<div onclick="clickColorInput(this)" title="click to select color"><label>BorderColor</label><input type="color" value="#000000" id="stroke"></div>',
'<div onclick="clickColorInput(this)" title="click to select color"><label>BackgroundColor</label><input type="color" value="#000000" id="backgroundColor"></div>',
'<div title="select range"><label style="margin-right: 20px;">BorderSize</label><input type="range" style="width: 80px;" id="strokeWidth" value="1" min="0" max="20" step="0.5"></div>',
'<div title="select range"><label style="margin-right: 20px;">Opacity</label><input type="range" style="width: 80px;" id="opacity" value="100" min="1" max="100" step="1"></div>',
'<div hidden=true id="ff-panel-screenshot" onclick="screenShotEl()" title="shot current rect"><label>Shot Current Rect</label><i class="fa fa-camera" style="font-size: 15px;" aria-hidden="true"></i></div>',
'<div onclick="delEl()" title="delete this object"><label>Delete</label><i class="fa fa-trash" style="font-size: 15px;" aria-hidden="true"></i></div>',
]
} [tips_language];
for (var i = 0; i < buttons_text.length; i++) {
var parent_button = document.createElement('div'); //add button 增加按钮
var outer_html = buttons_text[i];
parent_button.innerHTML = outer_html;
my_menu_node.appendChild(parent_button.childNodes[0]);
}
//listen color and opacity change 监听颜色变化和透明度变化
pdfAnnotation.observeValue('fill');
pdfAnnotation.observeValue('stroke');
pdfAnnotation.observeValue('backgroundColor');
pdfAnnotation.observeNumeric('opacity');
pdfAnnotation.observeNumeric('strokeWidth');
// setMenuInputBackgroundColor();
}
//create color control panel 创建颜色控制面板
function setColorControlForIE() {
var my_menu_node = document.getElementById('my-menu');
my_menu_node.innerHTML = ''; //clear 清空所有子元素
var buttons_text = {
'zh-cn': [
'<div title="关闭" onclick="hiddenMenu()"><label>关闭/close</label><i class="fa fa-times-circle" style="font-size: 15px;" aria-hidden="true"></i></div>',
'<div id="fold_or_open_div" title="折叠或展开面板" onclick="foldOrOpenMenu()"><label>折叠/展开面板</label><i class="fa fa-window-restore" style="font-size: 15px;margin-left:10px;" aria-hidden="true"></i></div>',
'<div title="点击色块修改颜色"><label>填充色</label><select type="color" id="fill"></select></div>',
'<div onclick="clickColorInput(this)" title="点击色块修改颜色"><label>边框色</label><select type="color" id="stroke"></select></div>',
'<div onclick="clickColorInput(this)" title="点击色块修改颜色"><label>背景色</label><select type="color" id="backgroundColor"></select></div>',
'<div title="拖动进度条调整"><label style="margin-right: 20px;">边框粗细</label><input type="range" style="width: 80px;" id="strokeWidth" value="1" min="0" max="20" step="0.5"></div>',
'<div title="拖动进度条调整"><label style="margin-right: 20px;">不透明度</label><input type="range" style="width: 80px;" id="opacity" value="100" min="1" max="100" step="1"></div>',
'<div hidden=true id="ff-panel-screenshot" onclick="screenShotEl()" title="截取当前区域"><label>截图当前区域</label><i class="fa fa-camera" style="font-size: 15px;" aria-hidden="true"></i></div>',
'<div onclick="delEl()" title="删除对象"><label>删除</label><i class="fa fa-trash" style="font-size: 15px;" aria-hidden="true"></i></div>',
],
'en': [
'<div title="Close" onclick="hiddenMenu()"><label>Close</label><i class="fa fa-times-circle" style="font-size: 15px;" aria-hidden="true"></i></div>',
'<div id="fold_or_open_div" title="fold or open panel" onclick="foldOrOpenMenu()"><label>Fold/Open Panel</label><i class="fa fa-window-restore" style="font-size: 15px;" aria-hidden="true"></i></div>',
'<div onclick="clickColorInput(this)" title="click to select color"><label>FillColor</label><select type="color" id="fill"></select></div>',
'<div onclick="clickColorInput(this)" title="click to select color"><label>BorderColor</label><select type="color" id="stroke"></select></div>',
'<div onclick="clickColorInput(this)" title="click to select color"><label>BackgroundColor</label><select type="color" id="backgroundColor"></select></div>',
'<div title="select range"><label style="margin-right: 20px;">BorderSize</label><input type="range" style="width: 80px;" id="strokeWidth" value="1" min="0" max="20" step="0.5"></div>',
'<div title="select range"><label style="margin-right: 20px;">Opacity</label><input type="range" style="width: 80px;" id="opacity" value="100" min="1" max="100" step="1"></div>',
'<div hidden=true id="ff-panel-screenshot" onclick="screenShotEl()" title="shot current rect"><label>Shot Current Rect</label><i class="fa fa-camera" style="font-size: 15px;" aria-hidden="true"></i></div>',
'<div onclick="delEl()" title="delete this object"><label>Delete</label><i class="fa fa-trash" style="font-size: 15px;" aria-hidden="true"></i></div>',
]
} [tips_language];
for (var i = 0; i < buttons_text.length; i++) {
var parent_button = document.createElement('div'); //add button 增加按钮
var outer_html = buttons_text[i];
parent_button.innerHTML = outer_html;
my_menu_node.appendChild(parent_button.childNodes[0]);
}
//设置颜色选择器
setSelections("fill");
setSelections("stroke");
setSelections("backgroundColor");
//listen color and opacity change 监听颜色变化和透明度变化
pdfAnnotation.observeIEValue('fill');
pdfAnnotation.observeIEValue('stroke');
pdfAnnotation.observeIEValue('backgroundColor');
pdfAnnotation.observeNumeric('opacity');
pdfAnnotation.observeNumeric('strokeWidth');
// setMenuInputBackgroundColor();
}
//选中文字后浮动菜单生成
function setHorAnnotationOperater() {
var buttons_text = {
'zh-cn': [
'<button title="撤销最后一个批注" id="ff-hor-undo-btn" onclick="undoAnnotation()" type="button"><span style="margin-right: 5px;">撤销</span><i class="fa fa-undo" aria-hidden="true"></i></button>',
'<button title="清空本人所有批注" id="ff-hor-clear-btn" onclick="clearFileAnnotations()" type="button"><span style="margin-right: 5px;">清空</span><i class="fa fa-trash" aria-hidden="true"></i></button>',
'<button title="选中对象" id="ff-pointer-obj-btn" onclick="setFabricTop(this)" type="button"><span style="margin-right: 5px;">选中</span><i class="fa fa-mouse-pointer" aria-hidden="true"></i></button>',
'<button title="提交后台保存批注" id="ff-save-upload-btn" onclick="outputAnnotations()" type="button"><span style="margin-right: 5px;">保存</span><i class="fa fa-upload" aria-hidden="true"></i></button>',
'<button title="关闭批注栏" id="ff-close-hor-btn" onclick="closeHorAnnotationButtons(0)" type="button"><span style="margin-right: 5px;">关闭</span><i class="fa fa-window-close" aria-hidden="true"></i></button>',
],
'en': [
'<button title="highlight selection text" id="ff-touch-highlight-btn" onclick="singleHighlightAndUnderline(0)" type="button"><span style="margin-right: 5px;">Highlight</span><i class="fa fa-paint-brush" aria-hidden="true"></i></button>',
'<button title="underline selection text" id="ff-touch-underline-btn" onclick="singleHighlightAndUnderline(1)" type="button"><span style="margin-right: 5px;">Underline</span><i class="fa fa-underline" aria-hidden="true"></i></button>',
'<button title="copy selection text" id="ff-touch-highlight-btn" onclick="singleCopy()" type="button"><span style="margin-right: 5px;">Copy</span><i class="fa fa-clipboard" aria-hidden="true"></i></button>',
'<button title="cancel selection" onclick="closeCopyConfirm()" type="button"><span style="margin-right: 5px;">Cancel</span><i class="fa fa-window-close" aria-hidden="true"></i></button>',
]
} [tips_language];
var single_buttons = document.getElementById('ff-hor-annotation-btn');
single_buttons.innerHTML = ''; //clear 清空所有子元素
for (var i = 0; i < buttons_text.length; i++) {
var parent_button = document.createElement('button'); //add button 增加按钮
var outer_html = buttons_text[i];
parent_button.innerHTML = outer_html;
single_buttons.appendChild(parent_button.childNodes[0]);
if (i != buttons_text.length - 1) {
var split_div = document.createElement('div');
split_div.classList.add('vertical-split');
single_buttons.appendChild(split_div);
}
}
}
function setLinkControl(){
var extract_pdf_html = {
'zh-cn': [
'<div class="linkform"><form class="selectform">'+
'<label><input type="radio" id="hy_url" checked="true" name="choice" value="url" onchange="handleSelection(this)"> URL</label>'+
'<label><input type="radio" id="hy_page" name="choice" value="page" onchange="handleSelection(this)"> 文档页面</label>'+
'<label><input type="radio" id="hy_file" name="choice" value="file" onchange="handleSelection(this)"> 在线文档#页面</label>'+
'</form>'+
'<p class="linktip" id="link_tips">请输入要跳转的URL</p>'+
'<input id="link_input" style="width: inherit;font-size: 15px;padding: 5px 3px 5px 3px;margin-bottom: 10px;" value="">'+
'<button type="button" onclick="linkToURL()" style="width: 80px;font-size: 15px;float: left;"><i style="padding: 5px;" class="fa fa-link" aria-hidden="true"></i>链接</button>'+
'<button type="button" onclick="unLink()" style="width: 100px;font-size: 15px;float: middle;"><i style="padding: 5px;" class="fa fa-unlink" aria-hidden="true"></i>取消链接</button>'+
'<button type="button" onclick="cancelLink()" style="width: 80px;font-size: 15px;float: right;"><i style="padding: 5px;" class="fa fa-times" aria-hidden="true"></i>关闭</button>'+
'</div>'
],
'en': [
'<div class="linkform"><form class="selectform">'+
'<label><input type="radio" id="hy_url" checked="true" name="choice" value="url" onchange="handleSelection(this)"> URL</label>'+
'<label><input type="radio" id="hy_page" name="choice" value="page" onchange="handleSelection(this)">Page</label>'+
'<label><input type="radio" id="hy_file" name="choice" value="file" onchange="handleSelection(this)">file#page</label>'+
'</form>'+
'<p class="linktip" id="link_tips">Enter URL you would like to link to</p>'+
'<input id="link_input" style="width: inherit;font-size: 15px;padding: 5px 3px 5px 3px;margin-bottom: 10px;" value="">'+
'<button type="button" onclick="linkToURL()" style="width: 90px;font-size: 15px;float: left;"><i style="padding: 5px;" class="fa fa-link" aria-hidden="true"></i>Link</button>'+
'<button type="button" onclick="unLink()" style="width: 90px;font-size: 15px;float: middle;"><i style="padding: 5px;" class="fa fa-unlink" aria-hidden="true"></i>Unlink</button>'+
'<button type="button" onclick="cancelLink()" style="width: 90px;font-size: 15px;float: right;"><i style="padding: 5px;" class="fa fa-times" aria-hidden="true"></i>Close</button>'+
'</div>'
]
} [tips_language];
document.getElementById('my-link-set-div').innerHTML = extract_pdf_html[0];
}
//选中文字后浮动菜单生成
function setSingleOperater() {
var buttons_text = {
'zh-cn': [
'<button title="高亮选中的文本" id="ff-touch-highlight-btn" onclick="singleHighlightAndUnderline(0)" type="button"><i class="fa fa-paint-brush" aria-hidden="true"></i></button>',
'<button title="为选中的文本添加下划线" id="ff-touch-underline-btn" onclick="singleHighlightAndUnderline(1)" type="button"><i class="fa fa-underline" aria-hidden="true"></i></button>',
'<button title="为选中的文本添加超链接" id="ff-touch-hyperlink-btn" onclick="showHyperLinkSet()" type="button"><i class="fa fa-link" aria-hidden="true"></i></button>',
'<button title="复制选中的文本" id="ff-touch-highlight-btn" onclick="singleCopy()" type="button"><i class="fa fa-clipboard" aria-hidden="true"></i></button>',
'<button title="取消选择" onclick="closeCopyConfirm()" type="button"><i class="fa fa-window-close" aria-hidden="true"></i></button>',
],
'en': [
'<button title="highlight selection text" id="ff-touch-highlight-btn" onclick="singleHighlightAndUnderline(0)" type="button"><i class="fa fa-paint-brush" aria-hidden="true"></i></button>',
'<button title="underline selection text" id="ff-touch-underline-btn" onclick="singleHighlightAndUnderline(1)" type="button"><i class="fa fa-underline" aria-hidden="true"></i></button>',
'<button title="hyperlink selection text" id="ff-touch-hyperlink-btn" onclick="showHyperLinkSet()" type="button"><i class="fa fa-link" aria-hidden="true"></i></button>',
'<button title="copy selection text" id="ff-touch-highlight-btn" onclick="singleCopy()" type="button"><i class="fa fa-clipboard" aria-hidden="true"></i></button>',
'<button title="cancel selection" onclick="closeCopyConfirm()" type="button"><i class="fa fa-window-close" aria-hidden="true"></i></button>',
]
} [tips_language];
var single_buttons = document.getElementById('ff-copyconfirm-btn');
single_buttons.innerHTML = ''; //clear 清空所有子元素
for (var i = 0; i < buttons_text.length; i++) {
var parent_button = document.createElement('button'); //add button 增加按钮
var outer_html = buttons_text[i];
parent_button.innerHTML = outer_html;
single_buttons.appendChild(parent_button.childNodes[0]);
// if (i != buttons_text.length - 1) {
// var split_div = document.createElement('div');
// split_div.classList.add('vertical-split');
// single_buttons.appendChild(split_div);
// }
}
var down_triangle = document.createElement('div');
down_triangle.innerHTML='<span class="triangle-down"><em></em></span>';
down_triangle.classList.add('popup');
single_buttons.appendChild(down_triangle);
}
// 顶部注释工具栏生成
function setAnnotationButtons() {
var buttons_text = [
'<button title="画笔工具" id="ff-free-draw" onclick="fabricDraw(this)" type="button" class="toolbarButton fontButton"><i class="fa fa-pencil" aria-hidden="true"><span></span></i></button>',
'<div class="show-connect-div" id="show_connect_div"></div>',
'<button title="撤销批注" id="ff-undo-btn" onclick="undoAnnotation()" type="button" class="toolbarButton fontButton"><i class="fa fa-undo" aria-hidden="true"><span></span></i></button>',
'<button title="重做批注" id="ff-redo-btn" onclick="redoAnnotation()" type="button" class="toolbarButton fontButton"><i style="transform: rotateY(180deg);" class="fa fa-undo" aria-hidden="true"><span></span></i></button>',
'<button title="清除本人所有批注" id="ff-clear-file-annotation-btn" onclick="clearFileAnnotations()" type="button" class="toolbarButton fontButton"><i class="fa fa-trash" aria-hidden="true"><span></span></i></button>',
'<div class="verticalToolbarSeparator"></div>',
'<button title="保存" id="ff-download-btn" onclick="mySave()" type="button" class="toolbarButton fontButton"><i class="fa fa-save" aria-hidden="true"><span></span></i></button>',
// '<button id="download" class="toolbarButton hiddenMediumView" title="Save" tabindex="33" data-l10n-id="save"> <span data-l10n-id="save_label">Save</span> </button>',
];
var annotation_buttons_node = document.getElementById('toolbarViewerRight');
var new_html = '';
for (var i = 0; i < buttons_text.length; i++) {
new_html += buttons_text[i];
}
annotation_buttons_node.innerHTML += new_html;
}
// function setAnnotationButtons() {
// // return;
// var annotation_buttons_node = document.getElementById('firefly-annotation-buttons');
//
// annotation_buttons_node.innerHTML = ''; //clear 清空所有子元素
// // '<div class="splitToolbarButtonSeparator"></div>'
// var buttons_text = {
// 'zh-cn': [
// '<div>',
// '<button title="下载批注后的文件(批注将标记在下载的文件中)" id="ff-download-btn" onclick="myDownLoad()" type="button"><i class="fa fa-folder" aria-hidden="true"><span></span></i></button>',
// '<button title="截取PDF部分页" id="ff-extract-pdf" onclick="extractPDF()" type="button"><i class="fa fa-map" aria-hidden="true"><span></span></i></button>',
// '<button title="导出标注(json格式)" id="ff-output-btn" onclick="outputAnnotations()" type="button"><i class="fa fa-upload" aria-hidden="true"><span></span></i></button>',
// '<button title="导入标注(json格式)" id="ff-import-btn" onclick="openAnnotationFile()" type="button"><i class="fa fa-download" aria-hidden="true"><span></span></i></button>',
// '<button title="下载注释(txt格式)" id="ff-download-btn" onclick="downloadAnnotations()" type="button"><i class="fa fa-arrow-circle-down" aria-hidden="true"><span></span></i></button>',
// '<button title="切换至英文" id="ff-language-btn" onclick="setLanguage(1)" type="button"><i class="fa fa-etsy" aria-hidden="true"><span></span></i></button>',
// '<button title="画笔、高亮及各类配置" id="ff-setting-btn" onclick="showOrHideSettingMenu()" type="button"><i class="fa fa-gear" aria-hidden="true"><span style="font-weight:600;margin-left:5px;">配置</span></i></button>',
// '</div>',
// '<div>',
// '<button title="选中对象" id="ff-pointer-obj" onclick="setFabricTop(this)" type="button"><i class="fa fa-mouse-pointer" aria-hidden="true"><span></span></i></button>',
// '<button title="编辑标注" id="ff-edit-btn" onclick="editAnnotation()" type="button"><i class="fa fa-list-ul" aria-hidden="true"><span></span></i></button>',
// '<button title="文本高亮(再次点击取消滑选标注)" id="ff-highlight-btn" onclick="clickTab(this)" type="button"><i class="fa fa-paint-brush" aria-hidden="true"><span></span></i></button>',
// '<button title="文本下划线(再次点击取消滑选标注)" id="ff-underline-btn" onclick="clickTab(this)" type="button"><i class="fa fa-underline" aria-hidden="true"><span></span></i></button>',
// '<button title="插入图片" id="ff-import-img" onclick="chooseImage()" type="button"><i class="fa fa-picture-o" aria-hidden="true"><span></span></i></button>',
// '<button title="页面截图" id="ff-screen-shot" onclick="addFabricObj(this,6)" type="button"><i class="fa fa-camera"><span></span></i></button>',
// '<button title="画笔工具" id="ff-free-draw" onclick="fabricDraw(this)" type="button"><i class="fa fa-pencil" aria-hidden="true"><span></span></i></button>',
// '<button title="文字工具" id="ff-add-text" onclick="addFabricObj(this,2)" type="button"><i class="fa fa-font" aria-hidden="true"><span></span></i></button>',
// '<button title="箭头工具" id="ff-add-arrow" onclick="addFabricObj(this,3)" type="button"><i class="fa fa-external-link-square" aria-hidden="true"><span></span></i></button>',
// '<button title="矩形工具" id="ff-add-rect" onclick="addFabricObj(this,4)" type="button"><i class="fa fa-window-maximize" aria-hidden="true"><span></span></i></button>',
// '<button title="圆形工具" id="ff-add-circle" onclick="addFabricObj(this,5)" type="button"><i class="fa fa-circle" aria-hidden="true"><span></span></i></button>',
// '<button title="直线工具" id="ff-add-line" onclick="addFabricObj(this,7)" type="button"><i class="fa fa-minus" aria-hidden="true"><span></span></i></button>',
// '<button title="超链接工具" id="ff-add-hyperlink" onclick="addFabricObj(this,10)" type="button"><i class="fa fa-link" aria-hidden="true"><span></span></i></button>',
// '<button title="身份印章工具" id="ff-add-stamp" onclick="addFabricObj(this,8)" type="button"><i class="fa fa-id-card" aria-hidden="true"><span></span></i></button>',
// '<button title="插入对勾" id="ff-extract-pdf" onclick="addFabricObj(this,9)" type="button"><i class="fa fa-check" aria-hidden="true"><span></span></i></button>',
// '</div>',
// '<div>',
// '<div class="show-connect-div" id="show_connect_div"></div>',
// '<button title="橡皮檫" id="ff-eraser-btn" onclick="clickTab(this)" type="button"><i class="fa fa-eraser" aria-hidden="true"><span></span></i></button>',
// '<button title="撤销批注" id="ff-undo-btn" onclick="undoAnnotation()" type="button"><i class="fa fa-undo" aria-hidden="true"><span></span></i></button>',
// '<button title="重做批注" id="ff-redo-btn" onclick="redoAnnotation()" type="button"><i style="transform: rotateY(180deg);" class="fa fa-undo" aria-hidden="true"><span></span></i></button>',
// '<button title="清除本人所有批注" id="ff-clear-file-annotation-btn" onclick="clearFileAnnotations()" type="button"><i class="fa fa-trash" aria-hidden="true"><span></span></i></button>',
// '<button title="帮助文档" id="ff-undo-btn" onclick="openHelpDoc()" type="button"><i class="fa fa-question-circle" aria-hidden="true"><span></span></i></button>',
// '</div>',
// ],
// 'en': [
// '<div>',
// '<button title="download pdf with annotations mark" id="ff-download-btn" onclick="myDownLoad()" type="button"><i class="fa fa-folder" aria-hidden="true"><span></span></i></button>',
// '<button title="PDF extracter" id="ff-extract-pdf" onclick="extractPDF()" type="button"><i class="fa fa-map" aria-hidden="true"><span></span></i></button>',
// '<button title="output annotations(json)" id="ff-output-btn" onclick="outputAnnotations()" type="button"><i class="fa fa-upload" aria-hidden="true"><span></span></i></button>',
// '<button title="import annotations(json)" id="ff-import-btn" onclick="openAnnotationFile()" type="button"><i class="fa fa-download" aria-hidden="true"><span></span></i></button>',
// '<button title="download annotations(txt)" id="ff-download-btn" onclick="downloadAnnotations()" type="button"><i class="fa fa-arrow-circle-down" aria-hidden="true"><span></span></i></button>',
// '<button title="change tips to Chinese" id="ff-language-btn" onclick="setLanguage(0)" type="button"><i class="fa fa-etsy" aria-hidden="true"><span></span></i></button>',
// '<button title="highlght brush width and colors setting" id="ff-setting-btn" onclick="showOrHideSettingMenu()" type="button"><i class="fa fa-gear" aria-hidden="true"><span style="font-weight:600;margin-left:5px;">Settings</span></i></button>',
// '</div>',
// '<div>',
// '<button title="select annotation object" id="ff-pointer-obj" onclick="setFabricTop(this)" type="button"><i class="fa fa-mouse-pointer" aria-hidden="true"><span></span></i></button>',
// '<button title="edit annotations" id="ff-edit-btn" onclick="editAnnotation()" type="button"><i class="fa fa-list-ul" aria-hidden="true"><span></span></i></button>',
// '<button title="highlight" id="ff-highlight-btn" onclick="clickTab(this)" type="button"><i class="fa fa-paint-brush" aria-hidden="true"><span></span></i></button>',
// '<button title="underline" id="ff-underline-btn" onclick="clickTab(this)" type="button"><i class="fa fa-underline" aria-hidden="true"><span></span></i></button>',
// '<button title="insert image" id="ff-import-img" onclick="chooseImage()" type="button"><i class="fa fa-picture-o" aria-hidden="true"><span></span></i></button>',
// '<button title="screen shot" id="ff-screen-shot" onclick="addFabricObj(this,6)" type="button"><i class="fa fa-camera"><span></span></i></button>',
// '<button title="free draw" id="ff-free-draw" onclick="fabricDraw(this)" type="button"><i class="fa fa-pencil" aria-hidden="true"><span></span></i></button>',
// '<button title="add text" id="ff-add-text" onclick="addFabricObj(this,2)" type="button"><i class="fa fa-font" aria-hidden="true"><span></span></i></button>',
// '<button title="add arrow" id="ff-add-arrow" onclick="addFabricObj(this,3)" type="button"><i class="fa fa-external-link-square" aria-hidden="true"><span></span></i></button>',
// '<button title="add rectangle" id="ff-add-rect" onclick="addFabricObj(this,4)" type="button"><i class="fa fa-window-maximize" aria-hidden="true"><span></span></i></button>',
// '<button title="add circle" id="ff-add-circle" onclick="addFabricObj(this,5)" type="button"><i class="fa fa-circle" aria-hidden="true"><span></span></i></button>',
// '<button title="add line" id="ff-add-line" onclick="addFabricObj(this,7)" type="button"><i class="fa fa-minus" aria-hidden="true"><span></span></i></button>',
// '<button title="add hyperlink" id="ff-add-hyperlink" onclick="addFabricObj(this,10)" type="button"><i class="fa fa-link" aria-hidden="true"><span></span></i></button>',
// '<button title="add id card stamp" id="ff-add-stamp" onclick="addFabricObj(this,8)" type="button"><i class="fa fa-id-card" aria-hidden="true"><span></span></i></button>',
// '<button title="add check" id="ff-extract-pdf" onclick="addFabricObj(this,9)" type="button"><i class="fa fa-check" aria-hidden="true"><span></span></i></button>',
// '</div>',
// '<div>',
// '<div class="show-connect-div" id="show_connect_div"></div>',
// '<button title="eraser" id="ff-eraser-btn" onclick="clickTab(this)" type="button"><i class="fa fa-eraser" aria-hidden="true"><span></span></i></button>',
// '<button title="undo annotation" id="ff-undo-btn" onclick="undoAnnotation()" type="button"><i class="fa fa-undo" aria-hidden="true"><span></span></i></button>',
// '<button title="redo annotation" id="ff-redo-btn" onclick="redoAnnotation()" type="button"><i style="transform: rotateY(180deg);" class="fa fa-undo" aria-hidden="true"><span></span></i></button>',
// '<button title="clear your all annotations" id="ff-clear-file-annotation-btn" onclick="clearFileAnnotations()" type="button"><i class="fa fa-trash" aria-hidden="true"><span></span></i></button>',
// '<button title="help" id="ff-undo-btn" onclick="openHelpDoc()" type="button"><i class="fa fa-question-circle" aria-hidden="true"><span></span></i></button>',
// '</div>',
// ]
// } [tips_language];
//
// var new_html = '';
// for (var i = 0; i < buttons_text.length; i++) {
// new_html += buttons_text[i];
// }
// annotation_buttons_node.innerHTML = new_html;
// }
//create help text and show 创建帮助文本并显示
function openHelpDoc() {
var helps = {
'zh-cn': [{
'title': '下载文件',
'detail': '下载批注后的文件,批注将标记在下载的文件中且不可撤销,如果需要编辑批注请打开未经本应用导入的文件',
},
{
'title': '文本高亮',
'detail': '高亮滑选的文本,对非黑色字体无效。',
},
{
'title': '文本下划线',
'detail': '给滑选的文本增加下划线,对非黑色字体无效。',
},
{
'title': '注释列表',
'detail': '打开注释列表并编辑(复制/删除/前往)',
},
{
'title': '选中对象',
'detail': '选中批注对象并修改',
},
{
'title': '插入图片',
'detail': '插入本地图片,会自动压缩图片',
},
{
'title': '画笔工具',
'detail': '在当前页面使用画笔工具自由绘制',
},
{
'title': '文本框工具',
'detail': '给当前页面添加可输入文本框',
},
{
'title': '箭头工具',
'detail': '给当前页面添加箭头',
},
{
'title': '矩形工具',
'detail': '给当前页面添加矩形框',
},
{
'title': '圆形工具',
'detail': '给当前页面添加圆',
},
{
'title': '导出注释',
'detail': '导出完整结构标注,用于给同名文件增加标注。',
},
{
'title': '导入标注',
'detail': '导入完整结构标注,用于给当前文件增加标注。',
},
{
'title': '下载标注',
'detail': '导出当前文件标注和评论为txt格式文档。',
},
{
'title': '切换语言',
'detail': '切换提示语言至英文',
},
{
'title': '帮助文档',
'detail': '打开帮助文档。',
},
],
'en': [{
'title': 'download',
'detail': 'download pdf with annotations mark, it can not be undo, if you want to modify annotations, please open source file',
}, {
'title': 'highlight',
'detail': 'highlight selected text, valid for only black text',
},
{
'title': 'underline',
'detail': 'underline selected text, valid for only black text',
},
{
'title': 'annotation list',
'detail': 'show annotation list and edit (copy/delete/gotp)',
},
{
'title': 'select object',
'detail': 'select annotation to modify',
},
{
'title': 'insert image',
'detail': 'insert image to current page and compress it',
},
{
'title': 'free draw',
'detail': 'free draw by brush in current page',
},
{
'title': 'text input box',
'detail': 'add text input box to current page',
},
{
'title': 'arrow tool',
'detail': 'add arrow to current page',
},
{
'title': 'rectangle tool',
'detail': 'add rectangle to current page',
},
{
'title': 'circle tool',
'detail': 'add circle to current page',
},
{
'title': 'output annotations',
'detail': 'output annotations for importing',
},
{
'title': 'import annotations',
'detail': 'import annotations for current file',
},
{
'title': 'download annotations',
'detail': 'download only annotations text and comments to txt',
},
{
'title': 'set language',
'detail': 'change tips language to Chinese',
},
{
'title': 'help',
'detail': 'open help file',
},
]
} [tips_language];
if (post_to_parent == true) {
helps = [{
'title': '下载文件',
'detail': '下载批注后的文件,批注将标记在下载的文件中且不可撤销,如果需要编辑批注请打开未经本应用导入的文件',
}, {
'title': '文本高亮',
'detail': '高亮滑选的文本,对非黑色字体无效。',
},
{
'title': '文本下划线',
'detail': '给滑选的文本增加下划线,对非黑色字体无效。',
},
{
'title': '注释列表',
'detail': '打开注释列表并编辑(复制/删除/前往)',
},
{
'title': '选中对象',
'detail': '选中批注对象并修改',
},
{
'title': '插入图片',
'detail': '插入本地图片,会自动压缩图片',
},
{
'title': '画笔工具',
'detail': '在当前页面使用画笔工具自由绘制',
},
{
'title': '文本框工具',
'detail': '给当前页面添加可输入文本框',
},
{
'title': '箭头工具',
'detail': '给当前页面添加箭头',
},
{
'title': '矩形工具',
'detail': '给当前页面添加矩形框',
},
{
'title': '圆形工具',
'detail': '给当前页面添加圆',
},
{
'title': '导出注释',
'detail': '导出完整结构标注,用于给同名文件增加标注。',
},
{
'title': '导入标注',
'detail': '导入完整结构标注,用于给当前文件增加标注。',
},
{
'title': '云端保存',
'detail': '将标注保存到云端,仅可用于云端文件。',
},
{
'title': '加载云端标注',
'detail': '用于云端标注未正确加载的情况。',
},
{
'title': '下载标注',
'detail': '导出当前文件标注和评论为txt格式文档。',
},
{
'title': '帮助文档',
'detail': '打开帮助文档。',
},
];
}
var help_str = {
'zh-cn': '帮助文档:\n祝使用愉快\n\n按钮功能说明:\n',
'en': 'help file for buttons introduction:\n',
} [tips_language];
var nums = ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '⑪', '⑫', '⑬', '⑭', '⑮', '⑯', '⑰', '⑱', '⑲', '⑳'];
for (var i = 0; i < helps.length; i++) {
var this_help = helps[i];
help_str += nums[i] + ' ' + this_help['title'] + ' : ' + this_help['detail'] + '\n';
}
alert(help_str);
};
//listen tips_language change 监听tips language 的变化
function setLanguage(op) {
var tips = {
'zh-cn': [
"提示语言已切换至中文",
"提示语言已切换至英文",
],
'en': [
'tips language changed to Chinese',
'tips language changed to English',
]
} [tips_language];
if (op == 0) {
tips_language = "zh-cn";
addOperationTips(tips[0]);
} else {
tips_language = "en";
addOperationTips(tips[1]);
}
//设置提示语言
pdfAnnotation.tips_language=tips_language;
pdfAnnotationUI.tips_language=tips_language;
pdfHighlight.tips_language=tips_language;
JSplump.tips_language=tips_language;
setAnnotationButtons();
setColorControl();
setSettingsControl(); //添加设置面板
setSingleOperater();
setExtractPDFDiv(); //提取 pdf 的组件
setLinkControl();
// setHorAnnotationOperater(); //设置水平按钮
//Listen again after switching languages 切换语言之后重新监听
pdfAnnotation.observeValue('fill');
pdfAnnotation.observeValue('stroke');
pdfAnnotation.observeValue('backgroundColor');
pdfAnnotation.observeNumeric('opacity');
pdfAnnotation.observeNumeric('strokeWidth');
setMenuInputBackgroundColor();
if (pdfAnnotationUI.show_annotation_list) {
pdfAnnotationUI.showAnnotationList();
}
};
//防止手机端双击缩放和清空添加状态
function preventDoubleClick(event) {
event.preventDefault();
};

View File

@ -0,0 +1,212 @@
var run_in_angular = true;
var is_droping_text = false;
var current_drop_text = '';
function listenFileDrag() {
var oDragWrap = document.getElementById('viewer');
//拖进
oDragWrap.addEventListener(
"dragenter",
function(e) {
e.preventDefault();
},
false
);
//拖离
oDragWrap.addEventListener(
"dragleave",
function(e) {
// dragleaveHandler(e);
},
false
);
//拖来拖去 , 一定要注意dragover事件一定要清除默认事件
//不然会无法触发后面的drop事件
oDragWrap.addEventListener(
"dragover",
function(e) {
e.preventDefault();
},
false
);
//扔
oDragWrap.addEventListener(
"drop",
function(e) {
dropHandler(e);
},
false
);
}
// listening paste
document.addEventListener('paste', function(event) {
if (is_hyper_link_highlight==true || is_hyper_edit==true){
return;
}
var isChrome = false;
if (event.clipboardData || event.originalEvent) {
var data = (event.clipboardData && event.clipboardData.items) || [];
// get paste text
var copied_text=event.clipboardData.getData('text');
if (copied_text.length!=0){
dropTextToPDF(copied_text);
return;
}else{
var bolb = null;
if ((data[0].kind == 'file') &&
(data[0].type.match('^image/'))) {
blob = data[0].getAsFile();
if (blob !== null) {
dropImageToPDF(blob);
}
}
// let div = document.querySelector("div")
// for (var i = 0; i < data.length; i += 1) {
// if ((data[i].kind == 'file') &&
// (data[i].type.match('^image/'))) {
// blob = data[i].getAsFile();
// if (blob !== null) {
// dropImageToPDF(blob);
// }
// }
// }
}
}
});
function dropHandler(e) {
console.log('拖放结果',e);
e.preventDefault(); //获取文件列表
//将本地图片拖拽到页面中后要进行的处理都在这
console.log('拖放结束', e.dataTransfer.getData("text"));
var fileList = e.dataTransfer.files;
console.log('文件列表', fileList);
if (fileList.length === 0) {
var this_drop_text = e.dataTransfer.getData("text");
if (this_drop_text.length != 0) {
// console.log('拖入了文字',drop_text);
// alert(drop_text);
dropTextToPDF(this_drop_text);
}
return;
}
// 检测文件是不是图片
if (fileList[0].type.indexOf("image") === -1) {
return;
}
//插入图片
dropImageToPDF(fileList[0]);
};
function dropTextToPDF(text) {
is_droping_text = true;
current_drop_text = text;
document.getElementById("ff-add-text").click();
}
function initialDropText() {
is_droping_text = false;
current_drop_text = '';
document.getElementById("ff-pointer-obj").click();
}
function dropImageToPDF(file) {
var blobURL;
try {
blobURL = URL.createObjectURL(file);
} catch (e) {
return;
}
const img = new Image();
img.setAttribute('crossOrigin', 'Anonymous');
img.src = blobURL;
img.onerror = function() {
URL.revokeObjectURL(this.src);
alert(tips[0]);
};
img.onload = function() {
const MAX_WIDTH = 500;
const MAX_HEIGHT = 500;
const MIME_TYPE = 'image/png';
const QUALITY = 1;
URL.revokeObjectURL(this.src);
const this_size = pdfAnnotation.calculateSize(
img,
MAX_WIDTH,
MAX_HEIGHT
);
var newWidth = this_size[0];
var newHeight = this_size[1];
const canvas = document.createElement('canvas');
canvas.width = newWidth;
canvas.height = newHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, newWidth, newHeight);
//销毁图片
image = null;
var new_image = new Image();
// The value is set to anonymous, indicating that CORS requests for this element will not set credential flags. You cannot export a canvas or an object on a canvas as a picture without setting it.
//值设置为 anonymous表示对此元素的 CORS 请求将不设置凭据标志。若不设置,无法将画布或画布上的对象导出为图片。
new_image.setAttribute('crossOrigin', 'Anonymous');
// console.log('加载文件');
new_image.onload = function() {
//插入图片对象
pdfAnnotation.insertImage(new_image);
new_image = null; //销毁图片
}
var img_data = canvas.toDataURL('image/png');
new_image.src = img_data;
}
}
function prepareImages(){
var tips = {
'zh-cn': [
'无法加载图片',
'添加评论',
'点击画布以插入图片',
],
'en': [
'can not load image',
'add comments',
'click canvas to insert image',
]
} [this.tips_language];
//activate selectable mode 激活选择模式
if (this.fabric_top == false) {
var top_node = document.getElementById('ff-pointer-obj');
pdfAnnotationUI.setFabricTop(top_node);
}
var that = this;
var fabricObj = this.getCurrentPageFabricCanvas();
var fabric_item_id = this.buildId(fabricObj.getObjects().length + 1);
if (fabricObj) {
var set_img = new fabric.Image(new_image, {
id: fabric_item_id,
member_id: that.getRandomMemberID(),
my_type: 'image',
comment: tips[1],
backup_opacity: 1,
});
set_img.crossOrigin = "Anonymous"; //这里是主要添加的属性
// fabricObj.add(set_img);
that.adding_item = set_img; //将图片作为待插入对象
that.current_click_type = 'add_image';
// console.log('图片加载成功');
// addOperationTips(tips[2]);
pdfAnnotationUI.changeMouseText(1); //修改鼠标文字
that.changeAllCanvasSelectState();
// that.saveAllFabricData();
}
}

View File

@ -0,0 +1,239 @@
// main function, load html and listen 主函数
window.onload = function() {
if (isIE11()) {
// 在IE11中执行特定操作
addCssForIE11();
}
pdfAnnotationUI.initControls();
var all_href = location.href;
var params = all_href.split('?')[1].split('&');
var file_id = params[0];
var oriUrl = file_id.split('=')[1];
var user = params.length > 1 ? params[1].split('=')[1] : null;
if (user) {
setCurrentMemberId({id: user, name: user});
}
// console.log('加载pdf');
// var oriUrl = 'example_new_link.pdf';
// var pdfUrl;
// pdfUrl=oriUrl;
// // openFile(oriUrl);
// window.PDFViewerApplication.open(pdfUrl); //open pdf 打开pdf文档
pdfAnnotation.openFile(oriUrl);
//监听加载是否完成
loadDetect();
// pdfAnnotationUI.addPinchListener(); // Listen gesture zoom 监听手势缩放
// listenFileDrag();
setAnnotationButtons(); //add annotation buttons 添加批注功能按钮
// setColorControl(); //Add color control panel 添加颜色控制面板
// setSettingsControl(); //添加设置面板
setExtractPDFDiv(); //提取 pdf 的组件
setLinkControl(); //超链接组件
setSingleOperater(); //add operation buttons after selection 增加选中后的操作按钮
// testSetAllMemberList(); //set member 设置用户
pdf_viewer = document.getElementById('viewer');
pdf_viewer.addEventListener("mouseup", function(event) {
var span_id_list=event.target.id.split('-');
if (span_id_list.length<3 || span_id_list[2]!='textspan'){
pdfHighlight.closeCopyConfirm();
return;
}
listenHighlight();
try{
postToParent(); //API
}catch(e){
console.error(e);
}
// event.preventDefault();
}, true);
//listen selectionchange 监听选区变化
// document.addEventListener("selectionchange", function(event) {
// console.log('选区变化');
// }, true);
//remove listen 监听删除
document.addEventListener("keydown", function(event) {
if (event.shiftKey) {
shiftKeyPressed = true;
// console.log('Shift键被按下');
}
if (event.key === "Delete") {
pdfAnnotation.delEl();
};
// console.log('event',event);
if (event.ctrlKey && event.keyCode === 90) {
// Your code here to handle the "ctrl+z" key combination
// console.log("ctrl+z pressed");
pdfAnnotation.undoAnnotation();
};
if (event.ctrlKey && event.keyCode === 89) {
// Your code here to handle the "ctrl+z" key combination
// console.log("ctrl+z pressed");
pdfAnnotation.redoAnnotation();
}
});
document.addEventListener('keyup', function(event) {
if (!event.shiftKey) {
shiftKeyPressed = false;
// console.log('Shift键被释放');
}
});
// pdf_viewer.addEventListener("dblclick", function(event) {
// // console.log('双击了页面');
// if (current_click_type!='select'){
// // console.log(event);
// var this_canvas = getCurrentClickCanvas(event);
// initialFabricState(this_canvas);//清空添加状态
// }
// event.preventDefault();
// }, true);
// console.log('域名',document.domain);
var that = this;
//listen file choosing and open 监听文件选择
var this_e = document.getElementById('choose_file');
this_e.addEventListener('change', function(e) {
setFileAnnotation(this_e, e);
this_e.value = null;
});
var inputElement = document.getElementById("image_insert");
// console.log('加载图片');
inputElement.addEventListener('change', function(ev) {
// console.log('插入图片');
onlaodImgToInsert(ev);
inputElement.value = null;
});
//ban mouse right click 禁止在菜单上的默认右键事件
var my_menu = document.getElementById('my-menu');
my_menu.oncontextmenu = function(e) {
e.preventDefault()
}
// //默认打开列表
// if (default_show_annotation_list==true){
// editAnnotation();
// // console.log('打开列表');
// pdfAnnotationUI.show_all_annotation_list=true;
// pdfAnnotationUI.showAnnotationList();
// // // //刷新批注显示列表
// // if (pdfAnnotationUI.show_annotation_list) {
// // }
// }
//历史框可标注
listenDrag("my_annotation_history");
}
window.onresize = function() { //监听屏幕的改变
setTimeout(function() {
JSplump.refreshConnections();
}, 100)
};
var interval = null;
function loadDetect() {
var tips = {
'zh-cn': [
'文档加载中...',
],
'en': [
'Loading PDF...',
]
} [tips_language];
pdfAnnotationUI.showDownloadLog(tips[0]);
interval = setInterval('loadPdf()', 1000);
}
function loadPdf() {
if (PDFViewerApplication.pdfDocument == null) {
console.info('Loading...');
} else {
//文档加载完成
clearInterval(interval);
setSettingsControl(); //添加设置面板
pdfAnnotationUI.closeDownloadLog();
if (hyper_open_file==true){
PDFViewerApplication.page=hyper_open_page;
hyper_open_file=false;
hyper_open_page=1;
}
}
}
//实现文件下载
function downFromATag(blobUrl,filename,option,tip){
//blobUrl为PDF数据可转换为base 64后上传至服务器
if (option==0){
//IE11的下载方式
//在IE环境下blobUrl是 blob转换到 base64时请注意区分
window.navigator.msSaveBlob(blobUrl,filename);
// window.navigator.msSaveOrOpenBlob(blobUrl, filename);
}else{
//非IE 11的下载方式
var a = document.createElement('a');
if (!a.click) {
throw new Error('DownloadManager: "a.click()" is not supported.');
}
a.href = blobUrl;
a.target = '_parent';
if ('download' in a) {
a.download = filename;
}
try{
postPDFData({
"filename":filename,
"file_blob_url_data":blobUrl,
});
}catch(e){
console.error(e);
}
(document.body || document.documentElement).appendChild(a);
a.click();
a.remove();
// alert(tip);
}
}
function postPDFData(function_name,new_content){
window.parent.postMessage({"type":0,"source":"pdfmaster",'function_name':function_name,"content":new_content},'*');
}
var down_load_file=true;
var return_data=false;
function getPDFBlobData(){
//get pdf blob data but not download file
down_load_file=false;
return_data=true;
PDFViewerApplication.download();
}
function getPDFBlobDataAndDownLoad(){
//get pdf blob data and download file
down_load_file=true;
return_data=true;
PDFViewerApplication.download();
}

View File

@ -0,0 +1,422 @@
// import "@babel/polyfill";
pdfwheel.Annotation.prototype.modifyPdf = async function(blobUrl, filename) {
var tips = {
'zh-cn': [
'初始化文档...',
'1/2 处理文档...',
'2/2 下载准备中...',
'1. 文档已自动下载,请留意浏览器下载窗口\n2. 若文档较大时则耗时较久,请耐心等待',
],
'en': [
'Initialing PDF...',
'1/2 Processing File...',
'2/2 Prepare for downloading...',
'1. File is downloading, please pay attention to the browser download window\n\n2. When the file is large, it will take a long time, please wait patiently.',
]
} [tips_language];
pdfAnnotationUI.showDownloadLog(tips[0]);
// increase();
var file_annotation = this.readFileAnnotations();
var havenot_annotation=true;
for (var key in file_annotation){
var this_annotation=file_annotation[key];
var string_obj=JSON.stringify(this_annotation.page_canvas.fabric_canvas_json.objects);
if (string_obj!=='{}'){
havenot_annotation=false;
break;
}
}
if (havenot_annotation==true){
pdfAnnotationUI.closeDownloadLog();
downFromATag(blobUrl, filename,1,tips[3]);
return;
}
pdfAnnotationUI.showDownloadLog(tips[1]);
// URL for request URL是要请求的地址
var existingPdfBytes = await window.fetch(blobUrl).then(res => res
.arrayBuffer());
// console.log('文件加载完成');
// var existingPdfBytes = blobUrl.arrayBuffer();
var pdfDoc = await window.PDFLib.PDFDocument.load(existingPdfBytes);
var pages = pdfDoc.getPages();
// console.log('批注pdf加载完成2', pages.length);
var pages_imgs = [];
var canvas_scale = 1;
for (var j = 0; j < pages.length; j++) {
var img = await this.drawCanvasForDownload(pages[j], j + 1, canvas_scale);
// console.log('图片链接',img);
if (img) {
// console.log('图片转换',img);
var eleImgCover = await pdfDoc.embedPng(img);
// console.log('图片转换完成',eleImgCover);
pages_imgs.push(eleImgCover);
} else {
pages_imgs.push(null);
}
}
pdfAnnotationUI.showDownloadLog(tips[2]);
var i = 0;
pages.forEach(item => {
// console.log('当前页面',i);
var this_img = pages_imgs[i];
// const pageRotation = getPageRotation(item);
if (this_img != null) {
var page_width = item.getSize().width;
var page_height = item.getSize().height;
const rotationAngle = item.getRotation().angle;
var draw_x;
var draw_y;
var this_scale;
var final_angle=0;
var draw_width;
var draw_height;
if (rotationAngle==90){
draw_x=page_width;
draw_y=0;
final_angle=90;
draw_width=page_height;
draw_height=page_width;
}else if(rotationAngle==180){
draw_x=page_width;
draw_y=page_height;
final_angle=180;
draw_width=page_width;
draw_height=page_height;
}else if(rotationAngle==270){
this_scale = this_img.width / page_width;
draw_x=0;
draw_y=page_height;
final_angle=270;
draw_width=page_height;
draw_height=page_width;
}else{
this_scale = this_img.width / page_width;
draw_x=0;
draw_y=0;
final_angle=0;
draw_width=page_width;
draw_height=page_height;
}
// console.log('页面旋转角度',rotationAngle);
item.drawImage(this_img, {
x: draw_x,
y: draw_y,
rotate: PDFLib.degrees(final_angle),
width: draw_width,
height: draw_height,
});
// if (this.add_water_mark == true) {
// item.drawText('https://demos.libertynlp.com', {
// x: 0,
// y: page_height / 2,
// size: 40,
// color: PDFLib.rgb(0, 0, 0),
// })
// }
}
i = i + 1;
})
//如果存在需要提取的页面
if (extract_page_numbers.length > 0) {
var new_pdfDoc = await PDFLib.PDFDocument.create();
for (var j = 0; j < pages.length - 1; j++) {
if (extract_page_numbers.indexOf(j) != -1) {
var [added_Page] = await new_pdfDoc.copyPages(pdfDoc, [j])
// Add the first copied page
new_pdfDoc.addPage(added_Page)
}
}
pdfDoc = new_pdfDoc;
//处理完之后置空
extract_page_numbers = [];
}
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
const blob = new Blob([await pdfDoc.save()], {
type: 'application/pdf'
});
// console.log('IE-批注转Blob完成');
downFromATag(blob, filename,0,tips[3]);
} else {
const pdfUrl = URL.createObjectURL(
new Blob([await pdfDoc.save()], {
type: 'application/pdf'
}),
);
// window.open(pdfUrl, '_blank');
// console.log('批注转Blob完成');
downFromATag(pdfUrl, filename,1,tips[3]);
}
pdfAnnotationUI.closeDownloadLog();
}
// wux 添加了 merge 方法,将 annotation 合并到 pdf 中。内容基本上是抄的上面 download 方法。
pdfwheel.Annotation.prototype.merge = async function(blob) {
var tips = {
'zh-cn': [
'初始化文档...',
'1/2 处理文档...',
'2/2 准备中...',
'1. 文档正在保存\n2. 若文档较大时则耗时较久,请耐心等待',
],
'en': [
'Initialing PDF...',
'1/2 Processing File...',
'2/2 Preparing...',
'1. File is saving,\n\n2. When the file is large, it will take a long time, please wait patiently.',
]
} [tips_language];
pdfAnnotationUI.showDownloadLog(tips[0]);
// increase();
var file_annotation = this.readFileAnnotations();
var havenot_annotation=true;
for (var key in file_annotation){
var this_annotation=file_annotation[key];
var string_obj=JSON.stringify(this_annotation.page_canvas.fabric_canvas_json.objects);
if (string_obj!=='{}'){
havenot_annotation=false;
break;
}
}
if (havenot_annotation==true){
pdfAnnotationUI.closeDownloadLog();
return pdfDoc;
}
pdfAnnotationUI.showDownloadLog(tips[1]);
//////////
// console.log('文件加载完成');
var existingPdfBytes = await blob.arrayBuffer();
var pdfDoc = await window.PDFLib.PDFDocument.load(existingPdfBytes);
var pages = pdfDoc.getPages();
//////////
// URL for request URL是要请求的地址
// console.log('文件加载完成');
// var existingPdfBytes = blobUrl.arrayBuffer();
// var pdfDoc = await window.PDFLib.PDFDocument.load(existingPdfBytes);
var pages = pdfDoc.getPages();
// console.log('批注pdf加载完成2', pages.length);
var pages_imgs = [];
var canvas_scale = 1;
for (var j = 0; j < pages.length; j++) {
var img = await this.drawCanvasForDownload(pages[j], j + 1, canvas_scale);
// console.log('图片链接',img);
if (img) {
// console.log('图片转换',img);
var eleImgCover = await pdfDoc.embedPng(img);
// console.log('图片转换完成',eleImgCover);
pages_imgs.push(eleImgCover);
} else {
pages_imgs.push(null);
}
}
pdfAnnotationUI.showDownloadLog(tips[2]);
var i = 0;
pages.forEach(item => {
// console.log('当前页面',i);
var this_img = pages_imgs[i];
// const pageRotation = getPageRotation(item);
if (this_img != null) {
var page_width = item.getSize().width;
var page_height = item.getSize().height;
const rotationAngle = item.getRotation().angle;
var draw_x;
var draw_y;
var this_scale;
var final_angle=0;
var draw_width;
var draw_height;
if (rotationAngle==90){
draw_x=page_width;
draw_y=0;
final_angle=90;
draw_width=page_height;
draw_height=page_width;
}else if(rotationAngle==180){
draw_x=page_width;
draw_y=page_height;
final_angle=180;
draw_width=page_width;
draw_height=page_height;
}else if(rotationAngle==270){
this_scale = this_img.width / page_width;
draw_x=0;
draw_y=page_height;
final_angle=270;
draw_width=page_height;
draw_height=page_width;
}else{
this_scale = this_img.width / page_width;
draw_x=0;
draw_y=0;
final_angle=0;
draw_width=page_width;
draw_height=page_height;
}
// console.log('页面旋转角度',rotationAngle);
item.drawImage(this_img, {
x: draw_x,
y: draw_y,
rotate: PDFLib.degrees(final_angle),
width: draw_width,
height: draw_height,
});
// if (this.add_water_mark == true) {
// item.drawText('https://demos.libertynlp.com', {
// x: 0,
// y: page_height / 2,
// size: 40,
// color: PDFLib.rgb(0, 0, 0),
// })
// }
}
i = i + 1;
})
//如果存在需要提取的页面
if (extract_page_numbers.length > 0) {
var new_pdfDoc = await PDFLib.PDFDocument.create();
for (var j = 0; j < pages.length - 1; j++) {
if (extract_page_numbers.indexOf(j) != -1) {
var [added_Page] = await new_pdfDoc.copyPages(pdfDoc, [j])
// Add the first copied page
new_pdfDoc.addPage(added_Page)
}
}
pdfDoc = new_pdfDoc;
//处理完之后置空
extract_page_numbers = [];
}
pdfAnnotationUI.closeDownloadLog();
const pdfBlob = new Blob([await pdfDoc.save()], {
type: 'application/pdf'
});
return pdfBlob;
}
// draw canvas and convert to pdf 绘制批注到 canvas 并转换为 png
pdfwheel.Annotation.prototype.drawCanvasForDownload = async function(item, page_number, scale) {
var old_fabric_obj = this.readFabricAnnotationsForPage(page_number);
if (old_fabric_obj) {
var width = parseFloat(old_fabric_obj.page_canvas.width);
var height = parseFloat(old_fabric_obj.page_canvas.height);
var anno_canvas = document.createElement("canvas");
anno_canvas.width = width;
anno_canvas.height = height;
var page_id = this.fabric_annos_id_tag + 'for-download-' + page_number.toString();
anno_canvas.setAttribute('id', page_id);
var canvas_container = document.getElementById('div-for-download-canvas');
canvas_container.appendChild(anno_canvas);
var this_fabric_canvas = new fabric.Canvas(page_id, {
includeDefaultValues: true,
isDrawingMode: false,
fireRightClick: true,
stopContextMenu: false,
backgroundColor: 'rgba(255, 255, 255, 0)',
});
async function loadImageFabricCanvas() {
return new Promise(resolve => {
this_fabric_canvas.loadFromJSON(old_fabric_obj.page_canvas.fabric_canvas_json,
function() {
var this_canvas = document.getElementById(page_id);
var pic_url = this_canvas.toDataURL('image/png');
canvas_container.innerHTML = '';
resolve(pic_url);
});
})
}
let this_pic_url = await loadImageFabricCanvas();
return this_pic_url;
}
return null;
}
/*
拓展功能
增加文字水印
*/
pdfwheel.Annotation.prototype.addWaterMark = async function(url) {
const existingPdfBytes = await fetch(url).then(res => res.arrayBuffer())
const pdfDoc = await window.PDFLib.PDFDocument.load(existingPdfBytes)
//遍历页面增加水印
const pages = pdfDoc.getPages();
var pages_imgs = [];
var canvas_scale = 2;
for (var j = 0; j < pages.length; j++) {
var page = pages[j];
var page_width = page.getSize().width;
var page_height = page.getSize().height;
// 生成水印对象
var img = await this.drawWaterMark(page_width * canvas_scale, page_height * canvas_scale);
var pdf_img = await pdfDoc.embedPng(img);
pages_imgs.push(pdf_img);
}
var i = 0;
pages.forEach(item => {
var this_img = pages_imgs[i];
var this_scale = this_img.width / page_width;
item.drawImage(this_img, {
x: 0,
y: 0,
width: this_img.width / this_scale,
height: this_img.height / this_scale,
});
i = i + 1;
})
// 已经处理好的数据
const pdfBuffer = await pdfDoc.save()
const pdfUrl = URL.createObjectURL(
new Blob([pdfBuffer], {
type: 'application/pdf'
}),
);
// 返回出去
return pdfUrl
}
pdfwheel.Annotation.prototype.openFile =async function(oriUrl) {
var pdfUrl;
if (add_water_mark == true) {
pdfAnnotationUI.showDownloadLog("文档水印处理中...");
pdfUrl = await this.addWaterMark(oriUrl);
pdfAnnotationUI.closeDownloadLog();
} else {
pdfUrl = oriUrl;
}
window.PDFViewerApplication.open(pdfUrl); //open pdf 打开pdf文档
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More