<h1>GSAP 3 convertCoordinates()</h1>
<p>The #redArm is being rotated and then inside of an onUpdate, <a href="https://greensock.com/docs/v3/Plugins/MotionPathPlugin/static.convertCoordinates()">MotionPathPlugin.convertCoordinates()</a> is used to map where the tip of the arm is located in the coordinate system of the #kolben element so that the tip of the #blueElement can be positioned there dynamically...in a totally different container element.</p>
<svg stroke-linecap="round" stroke-linejoin="round" viewBox="40 50 180 42">
  <path fill="none" stroke="#444" stroke-width="2" d="M150 89h54l.133-36h-54"/>
  <circle id="wheelPath" cx="71" cy="71" r="17.5"/>
  <polyline id="redArm" fill="none" stroke="red" stroke-width="4" stroke-opacity="0.7" points="71 71 88.5 71" />
  <g id="kolben">
    <path fill="none" stroke="#444" stroke-width="2" d="M186.211 54.511h15.964v33.184h-15.964z"/>
    <line id="blueArm" fill="none" stroke="blue" stroke-width="4" x1="88.5" y1="71" x2="194.5" y2="71" stroke-opacity="0.5" />
    <circle class="joint" cx="194.193" cy="71" r="1"/>
    <circle id="joint" class="joint" cx="88.5" cy="71" r="1"/>

@import url('https://fonts.googleapis.com/css?family=Signika+Negative:300,400&display=swap');
body {
  font-family: "Signika Negative", sans-serif; 
  font-weight: 300;
  background-color: #111;
  color: #aaa;
  text-align: center;
  padding: 5px 15px;
  font-size: 18px;

h1, h2, h3 {
  color: white;
p {
  font-weight: 300;
  max-width: 900px;
  display: inline-block;
  text-align: left;
  margin-top: 1px;

.joint, #wheelPath {
  stroke: black;
  fill: none;
  vector-effect: non-scaling-stroke;

#wheelPath {
  stroke: red;
  stroke-width: 4px;
  opacity: 0.4;
  stroke-dasharray: 12px 12px;
a {
  color: #88ce02;
  text-decoration: none;
  font-weight: 600;
a:hover {
  text-decoration: underline;

var redArm = document.querySelector("#redArm"),
    blueArm = document.querySelector("#blueArm"),
    joint = document.querySelector("#joint"),
    kolben = document.querySelector("#kolben"),
    duration = 5,
    radius = 17.5,

    // local coordinates in the redArm that'll be the joint. It's 17.5px wide so the right tip is at {x: 17.5, y: 0}    
    armTip = { x: radius, y: 0 };

var tl = gsap.timeline({ onUpdate: onUpdate, repeat: -1 })
  .to(redArm, {
    duration: duration,
    rotation: 360,
    ease: "none"
  }, 0)
  .to(kolben, {
    duration: duration / 2,
    x: -radius * 2,
    ease: "sine.inOut",
    repeat: 1,
    yoyo: true
  }, 0);  

function onUpdate() {
  // convert from redArm's local coordinates {x: 17.5, y: 0} into where that exact point would be in kolben's local coordinates.  
  var p = MotionPathPlugin.convertCoordinates(redArm, kolben, armTip);
  blueArm.setAttribute("x1", p.x);
  blueArm.setAttribute("y1", p.y);
  joint.setAttribute("cx", p.x);
  joint.setAttribute("cy", p.y);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://assets.codepen.io/16327/gsap-latest-beta.min.js
  2. https://assets.codepen.io/16327/MotionPathPlugin.min.js