preface

The APP was launched in the evening, and at five o ‘clock in the afternoon, several products temporarily requested to save the TWO-DIMENSIONAL code picture of an H5 page into the mobile phone album! This QR code is the qr code of the public number. The purpose of saving it to the album is to enable users to identify the QR code in wechat so as to follow the public number!

Get this requirement, only less than 3 hours of development time, no time to bicker, no time to think too much, done!

Long press function on mobile terminal

H5 picture save, is generally long press save, so, first of all to achieve a long press function.

Use touchStart and TouchEnd on mobile devices to do long press functions to prevent the browser from default behavior. Many browser events have default behavior. If you don’t block the default behavior, the browser will execute its default behavior. So stop it! Prevent is a modifier in vue. For more on modifiers, see event modifiers here.

html

<img
    class="code"
    src="@/images/cloudStallUp/[email protected]"
    @touchstart.prevent="touchin"
    @touchend.prevent="cleartime"
  />
Copy the code

js

touchin() {
  clearInterval(this.Loop); // Clear the timer again to prevent repeated registration of timers
  this.Loop = setTimeout((a)= > {
   // Long press here to execute the operation
  }, 1000);
},

// This method is mainly used to clear the timer after each finger is removed
cleartime() {
  clearInterval(this.Loop);
},
Copy the code

Implement a Dialog popover

Every UI framework has its own dialog popover. If your project uses a UI framework, just use it. If your project does not use a UI framework, it is necessary to implement a Dialog popover yourself

Not all projects need to use a UI framework, if the project is very simple, it doesn’t need to be. Forgive me for being a wheelie, I like to build my own wheel, even if it doesn’t work!

Write popovers using H5’s Dialog TAB.

html

<dialog ref="dialog">
  <div @click="saveImage">Save the picture</div>
  <div @click="closeDialog">cancel</div>
</dialog>
Copy the code

css

@function vw($px) { @return ($px / 750) * 100vw; } $c_dd: #dddddd; dialog { border: none; padding: 0; div { width: vw(750); font-size: vw(30); height: vw(80); line-height: vw(80); &:last-child { border-top: 1px solid $c_dd; }} / / Dialog ::backdrop backdrop (0, 0, 0, gba); }Copy the code

js

touchin() {
  clearInterval(this.Loop); // Clear the timer again to prevent repeated registration of timers
  this.Loop = setTimeout((a)= > {
   / / show
   this.$refs.dialog.showModal();
  }, 1000); },...Copy the code

Effect display:

The Dialog tag has some compatibility issues

So, we need a polyfill

The installation

npm install dialog-polyfill
Copy the code

Introduced in the page

import dialogPolyfill from 'dialog-polyfill'
Copy the code

Create a new dialog-polyfill. SCSS

dialog {
  position: absolute;
  left: 0; right: 0;
  width: -moz-fit-content;
  width: -webkit-fit-content;
  width: fit-content;
  height: -moz-fit-content;
  height: -webkit-fit-content;
  height: fit-content;
  margin: auto;
  border: solid;
  padding: 1em;
  background: white;
  color: black;
  display: block;
}

dialog:not([open]) {
  display: none;
}

dialog + .backdrop {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  background: rgba(0,0,0,0.1);
}

._dialog_overlay {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
}

dialog.fixed {
  position: fixed;
  top: 50%;
  transform: translate(0-50%); }Copy the code

Introduced in the page

@import "@/style/dialog-polyfill.scss";
Copy the code

With polyfill, the background CSS is different from the native CSS

/* Supports dialog */
dialog::backdrop { 
  background-color: green;
}
/* polyfill */
dialog + .backdrop { 
  background-color: green;
}
Copy the code

Use the polyfill

js

data() {
    return {
        dialog: null
    };
},
mounted() {
    this.dialog =  this.$refs.dialog;
    dialogPolyfill.registerDialog(this.dialog);
},
methods: {
    touchin() {
      clearInterval(this.Loop); // Clear the timer again to prevent repeated registration of timers
      this.Loop = setTimeout((a)= > {
       this.dialog.showModal();
      }, 1000); },... }Copy the code

Save pictures to your phone album

Save using the A label

// First consider using the A tag download
saveImage(url) {
  if(! url) {return new Error("Picture address is incorrect");
  }

  let a = document.createElement("a");
  a.href = url;
  a.download = "xxxxx";

  if (document.all) {
    a.click();
  } else {
    / / compatible Firfox
    var evt = document.createEvent("MouseEvents");
    evt.initEvent("click".true.true);
    a.dispatchEvent(evt);
  }
  this.closeDialog();
},

closeDialog() {
  this.dialog.close();
},
Copy the code

Self-test found that it is useful in PC, but useless in mobile terminal, this scheme is abandoned

Use the H5 + API

saveImage() {
    if (!window.plus) return;
    /* eslint-disable */
    plus.gallery.save(
      this.codeImg,
      () => {
        plus.nativeUI.alert("Saving image to album succeeded");
      },
      () => {
        plus.nativeUI.alert("Save failed"); });/* eslint-enable */
    this.closeDialog(); },...Copy the code

It was sad to find that we didn’t use it in our initial architecture design, but we gave it up. For more information, go to the 5+ App Development Guide here

Call the native ability of the APP aspect to implement the save function

Wrapped in mixin.js

// Call the app method
// androidName-> Android method name
// iosName->ios method name
// androidData-> Parameters passed to Android
// iosData-> Parameters sent to ios
// h5Fuc-> The function that is called when it is not android or ios
callAPPFunction(androidName, iosName, androidData, iosData, h5Fuc) {
  switch (true) {
    case this.UTILS.isAndroid:
      window.hitumedia_android_js[androidName](androidData);
      break;
    case this.UTILS.isIOS:
      window.webkit.messageHandlers[iosName].postMessage(iosData);
      break;
    default: h5Fuc; }},Copy the code

Use in main.js

// Import global mixin
import Mixin from "@/utils/mixin.js";
Vue.mixin(Mixin);
Copy the code

Use it on the page

data() {
    return {
      codeImg: require("@/images/cloudStallUp/[email protected]")}; },... saveImage() {const url = location.href.split("/") [2];
        For architectural reasons, we do not have a picture server, so we can only use the address of the project
        const postUrl = `http://${url}/activity/The ${this.codeImg}`;
        this.callAPPFunction("onDownImgs"."", postUrl, "");
        this.closeDialog(); },...Copy the code

OK, perfect implementation of requirements.

The last

After writing this function and passing the self-test, submit the product acceptance and then!! The product said: “It seems that the APP is rarely seen to save the TWO-DIMENSIONAL code, this function is not ~~~”

This feature is no longer available ~~~~~~~~~~~~~~~

From this practical example, conclude how the front-end solves the requirements problem:

  • 1, to a demand, must first and the product to determine whether the demand is necessary
  • 2, be sure to communicate with the project manager about the time. If it is estimated that a certain period of time cannot be completed, be sure to say clearly in advance
  • 3, do not overestimate their ability, not must not say will, will things, have to set aside a variable of time
  • 4. Do not accept temporary demands and let the product communicate with the project manager
  • 5, development, to calm down, a technology is useful in PC, mobile useless or useless in a mobile phone is normal, change a technology on the line
  • 6, ideas to open, some web end can not achieve the function, let the APP end to do, eloquence must be good
  • Don’t get angry, don’t get angry, a function developed, don’t also very normal, don’t get angry, fuck!