JavaScript 根本没有在 HTML 文件中运行

Posted

技术标签:

【中文标题】JavaScript 根本没有在 HTML 文件中运行【英文标题】:JavaScript not running at all in HTML file 【发布时间】:2021-08-09 08:53:30 【问题描述】:

我正在尝试制作签名板,但 JS(涂鸦线)在开发沙箱中工作,但在我合并文件时却不行。在关闭正文标签之前,我已将我的 CSS 放在头部标签和脚本之间,以允许 JS 在其他组件运行后运行。不确定是什么导致它无法运行。这里是初学者,所以如果我的问题太入门级,我深表歉意。任何帮助将不胜感激。

<html>
<head>
    <style>
        *,
      *::before,
      *::after 
        box-sizing: border-box;
      
      
      body 
        display: -webkit-box;
        display: -ms-flexbox;
        display: flex;
        -webkit-box-pack: center;
            -ms-flex-pack: center;
                justify-content: center;
        -webkit-box-align: center;
            -ms-flex-align: center;
                align-items: center;
        height: 100vh;
        width: 100%;
        -webkit-user-select: none;
           -moz-user-select: none;
            -ms-user-select: none;
                user-select: none;
        margin: 0;
        padding: 32px 16px;
        font-family: Helvetica, Sans-Serif;
      
      
      .signature-pad 
        
        position: relative;
        display: -webkit-box;
        display: -ms-flexbox;
        display: flex;
        -webkit-box-orient: vertical;
        -webkit-box-direction: normal;
            -ms-flex-direction: column;
                flex-direction: column;
        font-size: 10px;
        width: 100%;
        height: 100%;
        max-width: 700px;
        max-height: 460px;
        border: 1px solid #e8e8e8;
        background-color: #fff;
        box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.08) inset;
        border-radius: 4px;
        padding: 16px;
        cursor:  crosshair;
          cursor: url('https://staging-dovetail.kinsta.cloud/wp-content/uploads/2021/05/Pen-Cursor-1.png') 53 53, crosshair;
      
      
      
      .signature-pad::before,
      .signature-pad::after 
        position: absolute;
        z-index: -1;
        content: "";
        width: 40%;
        height: 10px;
        bottom: 10px;
        background: transparent;
        box-shadow: 0 8px 12px rgba(0, 0, 0, 0.4);
      
      
      .signature-pad::before 
        left: 20px;
        -webkit-transform: skew(-3deg) rotate(-3deg);
                transform: skew(-3deg) rotate(-3deg);
      
      
      .signature-pad::after 
        right: 20px;
        -webkit-transform: skew(3deg) rotate(3deg);
                transform: skew(3deg) rotate(3deg);
      
      
      .signature-pad--body 
        position: relative;
        -webkit-box-flex: 1;
            -ms-flex: 1;
                flex: 1;
        border: 1px solid #f4f4f4;
      
      
      canvas 
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        border-radius: 4px;
        box-shadow: 0 0 5px rgba(0, 0, 0, 0.02) inset;
      
      
      .signature-pad--footer 
        color: #C3C3C3;
        text-align: center;
        font-size: 1.2em;
        margin-top: 8px;
      
      
      .signature-pad--actions 
        display: -webkit-box;
        display: -ms-flexbox;
        display: flex;
        -webkit-box-pack: justify;
            -ms-flex-pack: justify;
                justify-content: space-between;
        margin-top: 8px;
      
      
      #github img 
        border: 0;
      
      
      #fileupload 
        display: none;
      
      
      form 
        display: table-row;
        margin-right: 5px;
      
      
      span[role=button] 
        display: table-cell;
        font-size: 1.2em;
      
      
      span[role=button],
      button 
        cursor: pointer;
        background-color: #e1e1e1;
        color: #000000;
        border: none;
        padding: 8px;
        margin-bottom: 8px;
      
      
      @media (max-width: 940px) 
        #github img 
          width: 90px;
          height: 90px;
        
      
      
      </style>
</head>
<body>
    <div id="signature-pad" class="signature-pad">
        <div class="signature-pad--body">
          <canvas>
            Update your browser to support the canvas element!
          </canvas>
        </div>
        <div class="signature-pad--footer">
          <div class="description">Sign above</div>
    
          <div class="signature-pad--actions">
            <form action="#" enctype="multipart/form-data">
              <label for="fileupload" id="buttonlabel">
                
              </label>
              <input type="file" id="fileupload" accept="image/*">
            </form>
            <div>
              <button type="button" class="button clear" data-action="clear">Clear</button>
    
            </div>
          </div>
        </div>
      </div>
    <script>
        const wrapper = document.getElementById("signature-pad")
    const clearButton = wrapper.querySelector("[data-action=clear]")
    const changeColorButton = wrapper.querySelector("[data-action=change-color]")
    const undoButton = wrapper.querySelector("[data-action=undo]")
    const savePNGButton = wrapper.querySelector("[data-action=save-png]")
    const saveJPGButton = wrapper.querySelector("[data-action=save-jpg]")
    const saveSVGButton = wrapper.querySelector("[data-action=save-svg]")
    const canvas = wrapper.querySelector("canvas")
    const fileSelector = document.getElementById('fileupload')
   
   // https://medium.com/the-everyday-developer/detect-file-mime-type-using-magic-numbers-and-javascript-16bc513d4e1e
   const verifyAndSetPictureAsBackground = (event) => 
     const file = event.target.files[0]
     const fReader = new FileReader()
     fReader.onloadend = (e) => 
       if (e.target.readyState === FileReader.DONE) 
         const uint = new Uint8Array(e.target.result)
         let bytes = []
         uint.forEach((byte) => bytes.push(byte.toString(16)))
         const hex = bytes.join('').toUpperCase()
         if (!(getMimeType(hex) === 'image/png' || getMimeType(hex) === 'image/gif' || getMimeType(hex) === 'image/jpeg')) 
           alert('Please choose a picture(.png, .gif, or .jpeg)')
           // https://***.com/a/35323290/1904223
           file = null
           fileSelector.value = ''
           if (!/safari/i.test(navigator.userAgent)) 
             fileSelector.type = ''
             fileSelector.type = 'file'
           
         
         if (file) 
           const dataURL = window.URL.createObjectURL(file)
           signaturePad.fromDataURL(dataURL)
         
       
     
     fReader.readAsArrayBuffer(file.slice(0, 4))
   
   
   const getMimeType = (signature) => 
     switch (signature) 
       case '89504E47':
         return 'image/png'
       case '47494638':
         return 'image/gif'
       case 'FFD8FFDB':
       case 'FFD8FFE0':
       case 'FFD8FFE1':
         return 'image/jpeg'
       default:
         return 'Not allowed filetype'
     
   
   
   fileSelector.addEventListener('change', verifyAndSetPictureAsBackground, false)
   
   const signaturePad = new SignaturePad(canvas, 
     // It's Necessary to use an opaque color when saving image as JPEG
     // this option can be omitted if only saving as PNG or SVG
     backgroundColor: 'rgb(255, 255, 255)'
   )
   
   // Adjust canvas coordinate space taking into account pixel ratio,
   // to make it look crisp on mobile devices.
   // This also causes canvas to be cleared.
   const resizeCanvas = () => 
     // When zoomed out to less than 100%, for some very strange reason,
     // some browsers report devicePixelRatio as less than 1
     // and only part of the canvas is cleared then.
      const ratio =  Math.max(window.devicePixelRatio || 1, 1)
   
     // This part causes the canvas to be cleared
     canvas.width = canvas.offsetWidth * ratio
     canvas.height = canvas.offsetHeight * ratio
     canvas.getContext("2d").scale(ratio, ratio)
   
     // This library does not listen for canvas changes, so after the canvas is automatically
     // cleared by the browser, SignaturePad#isEmpty might still return false, even though the
     // canvas looks empty, because the internal data of this library wasn't cleared. To make sure
     // that the state of this library is consistent with visual state of the canvas, you
     // have to clear it manually.
     signaturePad.clear()
   
   
   // On mobile devices it might make more sense to listen to orientation change,
   // rather than window resize events.
   window.onresize = resizeCanvas
   resizeCanvas()
   
   const download = (dataURL, filename) => 
     const blob = dataURLToBlob(dataURL)
     const url = window.URL.createObjectURL(blob)
   
     const a = document.createElement("a")
     a.style = "display: none"
     a.href = url
     a.download = filename
   
     document.body.appendChild(a)
     a.click()
   
     window.URL.revokeObjectURL(url)
   
   
   // One could simply use Canvas#toBlob method instead, but it's just to show
   // that it can be done using result of SignaturePad#toDataURL.
   function dataURLToBlob(dataURL) 
     // Code taken from https://github.com/ebidel/filer.js
      const parts = dataURL.split('base64,')
      const contentType = parts[0].split(":")[1]
      const raw = window.atob(parts[1])
      const rawLength = raw.length
      const uInt8Array = new Uint8Array(rawLength)
   
     for (let i = 0;  i < rawLength;  ++i) 
       uInt8Array[i] = raw.charCodeAt(i)
     
   
     return new Blob([uInt8Array],  type: contentType )
   
   
   clearButton.addEventListener("click", () => signaturePad.clear())
   
   undoButton.addEventListener("click", () => 
     const data = signaturePad.toData()
   
     if (data) 
       data.pop()  // remove the last dot or line
       signaturePad.fromData(data)
     
   )
   
   changeColorButton.addEventListener("click", () => 
     const r = Math.round(Math.random() * 255)
     const g = Math.round(Math.random() * 255)
     const b = Math.round(Math.random() * 255)
     const color = "rgb(" + r + "," + g + "," + b +")"
   
     signaturePad.penColor = color
   )
   
   savePNGButton.addEventListener("click", () => 
     if (signaturePad.isEmpty()) 
       alert("Please provide a signature first.")
      else 
       const dataURL = signaturePad.toDataURL()
       download(dataURL, "signature.png")
     
   )
   
   saveJPGButton.addEventListener("click", () => 
     if (signaturePad.isEmpty()) 
       alert("Please provide a signature first.")
      else 
       const dataURL = signaturePad.toDataURL("image/jpeg")
       download(dataURL, "signature.jpg")
     
   )
   
   saveSVGButton.addEventListener("click", () => 
     if (signaturePad.isEmpty()) 
       alert("Please provide a signature first.")
      else 
       const dataURL = signaturePad.toDataURL('image/svg+xml')
       download(dataURL, "signature.svg")
     
   )
   </script>
</body>
</html>

【问题讨论】:

【参考方案1】:

当您在浏览器中打开此文件时,您需要查看“开发人员工具”以在控制台中查找错误(如果您不知道如何操作:尝试右键单击您的网页并选择“检查”来自上下文菜单)

控制台会显示:

Uncaught ReferenceError: SignaturePad is not defined
    file:test.html:233

在第 233 行查找

const signaturePad = new SignaturePad(....

类 SignaturePad 在哪里定义?您是否将其放在单独的文件中?

【讨论】:

以上是关于JavaScript 根本没有在 HTML 文件中运行的主要内容,如果未能解决你的问题,请参考以下文章

Cordova + Xcode 7.3 (html + Javascript) 在构建和模拟时未更改或更新

执行AJAX返回HTML片段中的JavaScript脚本

JavaScript 和 HTML 文件没有在 UIWebView 中运行

使用 javascript 进行 HTML5 拖放 DOM 操作

你根本不懂Javascript: HTML事件捕获与冒泡

深入理解JavaScript系列:根本没有“JSON对象”这回事!