我想翻转或旋转此功能区文本以使其可读吗?

I want to flip or rotate this ribbon text to make it readable?

我不想旋转框,我只想旋转或翻转功能区框上的文本。

如果直接旋转盒子会干扰字符串动画。

(function(){
 var STATE_CLOSED = 0,
  STATE_DETACHED = 1,
  STATE_OPENED = 2,

  TAG_HEIGHT = 30,
  TAG_WIDTH = 200,
  MAX_STRAIN = 40,

  // Factor of page height that needs to be dragged for the
  // curtain to fall
  DRAG_THRESHOLD = 0.36;

  VENDORS = [ 'Webkit', 'Moz', 'O', 'ms' ];

 var dom = {
   ribbon: null,
   ribbonString: null,
   ribbonTag: null,
   curtain: null,
   closeButton: null
  },

  // The current state of the ribbon
  state = STATE_CLOSED,

  // Ribbon text, correlates to states
  closedText = '',
  detachedText = '',

  friction = 1.04;
  gravity = 1.5,

  // Resting position of the ribbon when curtain is closed
  closedX = TAG_WIDTH * 0.55,
  closedY = -TAG_HEIGHT * 0.1,

  // Resting position of the ribbon when curtain is opened
  openedX = TAG_WIDTH * 0.4,
  openedY = TAG_HEIGHT,

  velocity = 0,
  rotation = 45,

  curtainTargetY = 0,
  curtainCurrentY = 0,

  dragging = false,
  dragTime = 0,
  dragY = 0,

  anchorA = new Point( closedX, closedY ),
  anchorB = new Point( closedX, closedY ),

  mouse = new Point();

 function initialize() {

  dom.ribbon = document.querySelector( '.forkit' );
  dom.curtain = document.querySelector( '.forkit-curtain' );
  dom.closeButton = document.querySelector( '.forkit-curtain .close-button' );

  if( dom.ribbon ) {

   // Fetch label texts from DOM
   closedText = dom.ribbon.getAttribute( 'data-text' ) || '';
   detachedText = dom.ribbon.getAttribute( 'data-text-detached' ) || closedText;

   // Construct the sub-elements required to represent the
   // tag and string that it hangs from
   dom.ribbon.innerHTML = '<span class="string"></span><span class="tag">' + closedText + '</span>';
   dom.ribbonString = dom.ribbon.querySelector( '.string' );
   dom.ribbonTag = dom.ribbon.querySelector( '.tag' );

   // Bind events
   dom.ribbon.addEventListener( 'click', onRibbonClick, false );
   document.addEventListener( 'mousemove', onMouseMove, false );
   document.addEventListener( 'mousedown', onMouseDown, false );
   document.addEventListener( 'mouseup', onMouseUp, false );
   document.addEventListener( 'touchstart', onTouchStart, false);
   document.addEventListener( 'touchmove', onTouchMove, false);
   document.addEventListener( 'touchend', onTouchEnd, false);
   window.addEventListener( 'resize', layout, false );

   if( dom.closeButton ) {
    dom.closeButton.addEventListener( 'click', onCloseClick, false );
   }

   // Start the animation loop
   animate();
  }
 }

 function onMouseDown( event ) {
  if( dom.curtain && state === STATE_DETACHED ) {
   event.preventDefault();
   dragY = event.clientY;
   dragTime = Date.now();
   dragging = true;
  }
 }

 function onMouseMove( event ) {
  mouse.x = event.clientX;
  mouse.y = event.clientY;
 }

 function onMouseUp( event ) {
  if( state !== STATE_OPENED ) {
   state = STATE_CLOSED;
   dragging = false;
  }
 }

 function onTouchStart( event ) {
  if( dom.curtain && state === STATE_DETACHED ) {
   event.preventDefault();
   var touch = event.touches[0];
   dragY = touch.clientY;
   dragTime = Date.now();
   dragging = true;
  }
 }

 function onTouchMove( event ) {
  var touch = event.touches[0];
  mouse.x = touch.pageX;
  mouse.y = touch.pageY;
 }

 function onTouchEnd( event ) {
  if( state !== STATE_OPENED ) {
   state = STATE_CLOSED;
   dragging = false;
  }
 }

 function onRibbonClick( event ) {
  if( dom.curtain ) {
   event.preventDefault();

   if( state === STATE_OPENED ) {
    close();
   }
   else if( Date.now() - dragTime < 300 ) {
    open();
   }
  }
 }

 function onCloseClick( event ) {
  event.preventDefault();
  close();
 }

 function layout() {
  if( state === STATE_OPENED ) {
   curtainTargetY = window.innerHeight;
   curtainCurrentY = curtainTargetY;
  }
 }

 function open() {
  dragging = false;
  state = STATE_OPENED;
 }

 function close() {
  dragging = false;
  state = STATE_CLOSED;
  dom.ribbonTag.innerHTML = closedText;
 }

 function detach() {
  state = STATE_DETACHED;
  dom.ribbonTag.innerHTML = detachedText;
 }

 function animate() {
  update();
  render();

  requestAnimFrame( animate );
 }

 function update() {
  // Distance between mouse and top right corner
  var distance = distanceBetween( mouse.x, mouse.y, window.innerWidth, 0 );

  // If we're OPENED the curtainTargetY should ease towards page bottom
  if( state === STATE_OPENED ) {
   curtainTargetY = Math.min( curtainTargetY + ( window.innerHeight - curtainTargetY ) * 0.2, window.innerHeight );
  }
  else {

   // Detach the tag when hovering close enough
   if( distance < TAG_WIDTH * 1.5 ) {
    detach();
   }
   // Re-attach the tag if the user moved away
   else if( !dragging && state === STATE_DETACHED && distance > TAG_WIDTH * 2 ) {
    close();
   }

   if( dragging ) {
    // Updat the curtain position while dragging
    curtainTargetY = Math.max( mouse.y - dragY, 0 );

    // If the threshold is crossed, open the curtain
    if( curtainTargetY > window.innerHeight * DRAG_THRESHOLD ) {
     open();
    }
   }
   else {
    curtainTargetY *= 0.8;
   }

  }

  // Ease towards the target position of the curtain
  curtainCurrentY += ( curtainTargetY - curtainCurrentY ) * 0.3;

  // If we're dragging or detached we need to simulate
  // the physical behavior of the ribbon
  if( dragging || state === STATE_DETACHED ) {

   // Apply forces
   velocity /= friction;
   velocity += gravity;

   var containerOffsetX = dom.ribbon.offsetLeft;

   var offsetX = Math.max( ( ( mouse.x - containerOffsetX ) - closedX ) * 0.2, -MAX_STRAIN );

   anchorB.x += ( ( closedX + offsetX ) - anchorB.x ) * 0.1;
   anchorB.y += velocity;

   var strain = distanceBetween( anchorA.x, anchorA.y, anchorB.x, anchorB.y );

   if( strain > MAX_STRAIN ) {
    velocity -= Math.abs( strain ) / ( MAX_STRAIN * 1.25 );
   }

   var dy = Math.max( mouse.y - anchorB.y, 0 ),
    dx = mouse.x - ( containerOffsetX + anchorB.x );

   // Angle the ribbon towards the mouse but limit it avoid extremes
   var angle = Math.min( 130, Math.max( 50, Math.atan2( dy, dx ) * 180 / Math.PI ) );

   rotation += ( angle - rotation ) * 0.1;
  }
  // Ease ribbon towards the OPENED state
  else if( state === STATE_OPENED ) {
   anchorB.x += ( openedX - anchorB.x ) * 0.2;
   anchorB.y += ( openedY - anchorB.y ) * 0.2;

   rotation += ( 90 - rotation ) * 0.02;
  }
  // Ease ribbon towards the CLOSED state
  else {
   anchorB.x += ( anchorA.x - anchorB.x ) * 0.2;
   anchorB.y += ( anchorA.y - anchorB.y ) * 0.2;

   rotation += ( 135 - rotation ) * 0.2;
  }
 }

 function render() {

  if( dom.curtain ) {
   dom.curtain.style.top = - 100 + Math.min( ( curtainCurrentY / window.innerHeight ) * 100, 100 ) + '%';
  }

  dom.ribbon.style[ prefix( 'transform' ) ] = transform( 0, curtainCurrentY, 0 );
  dom.ribbonTag.style[ prefix( 'transform' ) ] = transform( anchorB.x, anchorB.y, rotation );

  var dy = anchorB.y - anchorA.y,
   dx = anchorB.x - anchorA.x;

  var angle = Math.atan2( dy, dx ) * 180 / Math.PI;

  dom.ribbonString.style.width = anchorB.y + 'px';
  dom.ribbonString.style[ prefix( 'transform' ) ] = transform( anchorA.x, 0, angle );

 }

 function prefix( property, el ) {
  var propertyUC = property.slice( 0, 1 ).toUpperCase() + property.slice( 1 );

  for( var i = 0, len = VENDORS.length; i < len; i++ ) {
   var vendor = VENDORS[i];

   if( typeof ( el || document.body ).style[ vendor + propertyUC ] !== 'undefined' ) {
    return vendor + propertyUC;
   }
  }

  return property;
 }

 function transform( x, y, r ) {
  return 'translate('+x+'px,'+y+'px) rotate('+r+'deg)';
 }

 function distanceBetween( x1, y1, x2, y2 ) {
  var dx = x1-x2;
  var dy = y1-y2;
  return Math.sqrt(dx*dx + dy*dy);
 }

 /**
  * Defines a 2D position.
  */
 function Point( x, y ) {
  this.x = x || 0;
  this.y = y || 0;
 }

 Point.prototype.distanceTo = function( x, y ) {
  var dx = x-this.x;
  var dy = y-this.y;
  return Math.sqrt(dx*dx + dy*dy);
 };

 Point.prototype.clone = function() {
  return new Point( this.x, this.y );
 };

 Point.prototype.interpolate = function( x, y, amp ) {
  this.x += ( x - this.x ) * amp;
  this.y += ( y - this.y ) * amp;
 };

 window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame   ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame  ||
    window.oRequestAnimationFrame  ||
    window.msRequestAnimationFrame  ||
    function( callback ){
     window.setTimeout(callback, 1000 / 60);
    };
 })();

 initialize();

})();
.forkit-curtain {
 text-align: center;
 background: rgba( 0, 0, 0, 0.8 );
 padding-top: 0%;
}
 
.forkit-curtain  .close-button {
  position: absolute;
  width: 32px;
  height: 32px;
  right: 20px;
  top: 20px;
  cursor: pointer;

  background: url(data:image/png;base64,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);
 }

.forkit {
 position: absolute;
 left: 0;
 top: 0;
  
    
 width: 200px;
 height: 150px;

 font-family: 'Lato', sans-serif;
 text-decoration: none;
}
 .forkit .tag {
  display: block;
  height: 30px;
  width: 200px;
        
    
  color: #fff;
  background: #aaa000;
  text-align: center;
  font-size: 13px;
  font-weight: bold;
  line-height: 30px;
  box-shadow: 0px 0px 10px rgba( 0, 0, 0, 0.4 );

  -webkit-transform-origin: 15px 0px;
     -moz-transform-origin: 15px 0px;
      -ms-transform-origin: 15px 0px;
       -o-transform-origin: 15px 0px;
          transform-origin: 15px 0px;
 }
 .forkit .tag:after {
  content: '';
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 196px;
  height: 26px;
  margin: 1px;
  border: 1px solid rgba( 255, 255, 255, 0.4 );
 }
 .forkit .string {
  display: block;
  height: 1px;
  width: 0px;
  position: absolute;

  background: rgba( 0, 0, 204, 0.8 );
  box-shadow: 0px 0px 10px rgba( 0,0,255,0.3 );

  -webkit-transform-origin: 0px 0px;
     -moz-transform-origin: 0px 0px;
      -ms-transform-origin: 0px 0px;
       -o-transform-origin: 0px 0px;
          transform-origin: 0px 0px;
 }


.forkit-curtain {
 position: absolute;
 width: 100%;
 height: 100%;
 top: -100%;
}
<p>This allows us to fill areas with transparent color; the first thee numbers representing the color in RGB values and the fourth representing a transparency value between 0 and 1 (zero being fully transparent and one being fully opaque). We have long had the opacity property, which is similar, but opacity forces all decendant elements to also become transparent and there is no way to fight it (except weird positional hacks) Cross-browser opacity is also a bit sloppy.</p>

JSFiddle

将此添加到 CSS 文档的底部。

#ribbonText{
transform: rotate(180deg)
}

并将 forkit 锚标记更改为这个-

    <a class="forkit" data-text="<div id='ribbonText'>10% Discount</div>"
data-text-detached="Drag down >" href=""></a>