Scratch for a Message

 Probably one of my favorite ideas — a little hidden message that visitors have to scratch away to reveal.

You can use it for affirmations, tiny surprises, daily messages, or anything you want to keep hidden until someone interacts with it. I like that it makes something as simple as visiting a blog feel a little more playful.


Code:

<style>

/* ================================

   WHOLE WIDGET

   ================================ */


.spy-scratch-widget {

  width: 100%;

  max-width: 300px;

  margin: 10px auto;

  box-sizing: border-box;

}



/* ================================

   WHITE MESSAGE BOX

   THIS IS THE ONLY SCRATCH AREA

   ================================ */


.spy-message-box {

  position: relative;


  width: 100%;

  height: 145px;


  background: #FFFFFF;


  border: 2px solid #111111;

  border-radius: 8px;


  overflow: hidden;


  box-sizing: border-box;

}



/* ================================

   AFFIRMATION

   ================================ */


.spy-affirmation {

  position: absolute;


  top: 0;

  left: 0;


  width: 100%;

  height: 100%;


  padding: 20px;


  box-sizing: border-box;


  display: flex;

  align-items: center;

  justify-content: center;


  background: #FFFFFF;


  font-family: Georgia, serif;

  font-size: 16px;

  line-height: 1.4;


  color: #222222;


  text-align: center;


  z-index: 1;

}



/* ================================

   SCRATCH CANVAS

   EXACTLY THE SIZE OF MESSAGE BOX

   ================================ */


.spy-scratch-canvas {

  position: absolute !important;


  top: 24% !important;

  left: 4% !important;


  width: 92% !important;

  height: 57% !important;


  margin: 0 !important;

  padding: 0 !important;


  display: block !important;


  z-index: 5;


  cursor: crosshair;


  touch-action: none;

}



/* ================================

   SCRATCH HERE

   ================================ */


.spy-scratch-text {

  position: absolute;


  top: 50%;

  left: 50%;


  transform: translate(-50%, -50%);


  z-index: 10;


  pointer-events: none;


  font-family: Unkempt, cursive;


  font-size: 18px;

  font-weight: bold;


  color: #FFFFFF;


  white-space: nowrap;


  text-shadow:

    1px 1px 0 #111111,

    -1px -1px 0 #111111,

    1px -1px 0 #111111,

    -1px 1px 0 #111111;


  transition: opacity 0.2s ease;

}



/* ================================

   NEW MESSAGE BUTTON

   OUTSIDE SCRATCH AREA

   ================================ */


.spy-new-message {

  display: block;


  margin: 9px auto 0;


  padding: 6px 12px;


  background: #FFFFFF;


  border: 2px solid #111111;

  border-radius: 5px;


  color: #111111;


  font-family: Arial, sans-serif;


  font-size: 9px;

  font-weight: bold;


  cursor: pointer;


  box-shadow: 2px 2px 0 #111111;

}


.spy-new-message:hover {

  background: #F7C8F0;

}


.spy-new-message:active {

  transform: translate(1px, 1px);

}

</style>



<!-- =========================================

     WIDGET

     ========================================= -->


<div class="spy-scratch-widget">



  <!-- =======================================

       ONLY THIS WHITE BOX IS SCRATCHABLE

       ======================================= -->


  <div class="spy-message-box">



    <!-- AFFIRMATION UNDERNEATH -->


    <div

      class="spy-affirmation"

      id="spyAffirmation"

    >

      You are exactly where you need to be.

    </div

></div>



    <!-- PURPLE SCRATCH LAYER -->


    <canvas

      class="spy-scratch-canvas"

      id="spyScratchCanvas"

    >



    <!-- SCRATCH HERE -->


    <div

      class="spy-scratch-text"

      id="spyScratchText"

    >

      SCRATCH HERE

    </div

></canvas

></div>



  



  <!-- =======================================

       THIS IS OUTSIDE THE SCRATCH AREA

       ======================================= -->


  <button

    type="button"

    class="spy-new-message"

    id="spyNewMessage"

  >

    NEW MESSAGE

  






<script>


(function() {


  /* =========================================

     AFFIRMATIONS

     ========================================= */


  var affirmations = [


    "You are exactly where you need to be.",


    "Good things are allowed to happen to you.",


    "You do not have to have everything figured out.",


    "Take your time. There is no rush.",


    "You are doing better than you think.",


    "You deserve a beautiful day.",


    "Trust yourself and your instincts.",


    "You are allowed to start again.",


    "You are more capable than you realize.",


    "Your timing does not have to look like anyone else's.",


    "You are allowed to change your mind.",


    "Something lovely may be closer than you think.",


    "Your dreams are worth making room for.",


    "You are allowed to rest without earning it.",


    "Small progress is still progress.",


    "You are worthy of good things.",


    "You can begin again whenever you want.",


    "You do not have to rush your life.",


    "You are allowed to choose yourself.",


    "Something good can find you today.",


    "You deserve softness and beautiful surprises.",


    "There is still so much good waiting for you.",


    "You are becoming someone you will be proud of.",


    "Your life does not need to look like anyone else's.",


    "You are allowed to romanticize the little things."


  ];



  /* =========================================

     ELEMENTS

     ========================================= */


  var canvas =

    document.getElementById(

      "spyScratchCanvas"

    );


  var canvasBox =

    document.querySelector(

      ".spy-message-box"

    );


  var ctx =

    canvas.getContext("2d");


  var scratchText =

    document.getElementById(

      "spyScratchText"

    );


  var affirmation =

    document.getElementById(

      "spyAffirmation"

    );


  var newMessage =

    document.getElementById(

      "spyNewMessage"

    );



  var scratching = false;



  /* =========================================

     RANDOM AFFIRMATION

     ========================================= */


  function randomAffirmation() {


    var number =

      Math.floor(

        Math.random() *

        affirmations.length

      );


    affirmation.textContent =

      affirmations[number];


  }



  /* =========================================

     CREATE PURPLE SCRATCH SURFACE

     ========================================= */


  function createScratchSurface() {


    /*

      Get dimensions ONLY from

      the white affirmation box.

    */


    var width =

      canvasBox.clientWidth;


    var height =

      canvasBox.clientHeight;



    canvas.width =

      width;


    canvas.height =

      height;



    /*

      Make the actual canvas visually

      exactly the same dimensions.

    */


    canvas.style.width =

      width + "px";


    canvas.style.height =

      height + "px";



    /*

      Paint the purple scratch layer.

    */


    ctx.globalCompositeOperation =

      "source-over";



    ctx.fillStyle =

      "#B866AD";



    ctx.fillRect(

      0,

      0,

      width,

      height

    );



    /*

      Reset instruction.

    */


    scratchText.style.opacity =

      "1";


  }



  /* =========================================

     ERASE PURPLE

     ========================================= */


  function erase(event) {


    if (!scratching) {

      return;

    }



    event.preventDefault();



    var rectangle =

      canvas.getBoundingClientRect();



    var x;

    var y;



    /*

      MOUSE

    */


    if (

      event.type.indexOf("touch") === -1

    ) {


      x =

        event.clientX -

        rectangle.left;


      y =

        event.clientY -

        rectangle.top;


    }



    /*

      TOUCH

    */


    else {


      x =

        event.touches[0].clientX -

        rectangle.left;


      y =

        event.touches[0].clientY -

        rectangle.top;


    }



    /*

      ERASE THE PURPLE

    */


    ctx.globalCompositeOperation =

      "destination-out";



    ctx.beginPath();


    ctx.arc(

      x,

      y,

      22,

      0,

      Math.PI * 2

    );


    ctx.fill();



    /*

      Hide "SCRATCH HERE"

      once they start scratching.

    */


    scratchText.style.opacity =

      "0";


  }



  /* =========================================

     MOUSE INTERACTION

     ========================================= */


  canvas.addEventListener(

    "mouseenter",

    function() {


      scratching = true;


    }

  );



  canvas.addEventListener(

    "mousedown",

    function(event) {


      scratching = true;


      erase(event);


    }

  );



  canvas.addEventListener(

    "mousemove",

    function(event) {


      /*

        Mouse movement over the

        purple canvas erases it.

      */


      if (scratching) {


        erase(event);


      }


    }

  );



  canvas.addEventListener(

    "mouseup",

    function() {


      scratching = false;


    }

  );



  canvas.addEventListener(

    "mouseleave",

    function() {


      scratching = false;


    }

  );



  /* =========================================

     TOUCH / MOBILE

     ========================================= */


  canvas.addEventListener(

    "touchstart",

    function(event) {


      event.preventDefault();


      scratching = true;


      erase(event);


    },

    { passive: false }

  );



  canvas.addEventListener(

    "touchmove",

    function(event) {


      event.preventDefault();


      erase(event);


    },

    { passive: false }

  );



  canvas.addEventListener(

    "touchend",

    function() {


      scratching = false;


    }

  );



  /* =========================================

     NEW MESSAGE

     ========================================= */


  newMessage.addEventListener(

    "click",

    function() {


      randomAffirmation();


      createScratchSurface();


    }

  );



  /* =========================================

     INITIALIZE

     ========================================= */


  randomAffirmation();


  createScratchSurface();



  /* =========================================

     RESIZE

     ========================================= */


  window.addEventListener(

    "resize",

    function() {


      createScratchSurface();


    }

  );


})();


</script></button

>

No comments:

Post a Comment