diff --git a/doric-Qt/example/app/qml.qrc b/doric-Qt/example/app/qml.qrc
index 9a6307ca..de133e09 100644
--- a/doric-Qt/example/app/qml.qrc
+++ b/doric-Qt/example/app/qml.qrc
@@ -48,6 +48,7 @@
         ../doric/resources/slide-item.qml
         ../doric/resources/input.qml
         ../doric/resources/switch.qml
+        ../doric/resources/draggable.qml
 
         ../doric/resources/toast.qml
         ../doric/resources/alert.qml
diff --git a/doric-Qt/example/doric/DoricRegistry.cpp b/doric-Qt/example/doric/DoricRegistry.cpp
index cadcccdd..c9519ad5 100644
--- a/doric-Qt/example/doric/DoricRegistry.cpp
+++ b/doric-Qt/example/doric/DoricRegistry.cpp
@@ -7,6 +7,7 @@
 #include "plugin/DoricShaderPlugin.h"
 #include "plugin/DoricStoragePlugin.h"
 
+#include "shader/DoricDraggableNode.h"
 #include "shader/DoricHLayoutNode.h"
 #include "shader/DoricImageNode.h"
 #include "shader/DoricInputNode.h"
@@ -37,6 +38,7 @@ DoricRegistry::DoricRegistry() {
   registerViewNode("SlideItem");
   registerViewNode("Input");
   registerViewNode("Switch");
+  registerViewNode("Draggable");
 }
 
 bool DoricRegistry::acquirePluginInfo(QString name) {
diff --git a/doric-Qt/example/doric/doric.pro b/doric-Qt/example/doric/doric.pro
index 52c4e13f..a61d9c20 100644
--- a/doric-Qt/example/doric/doric.pro
+++ b/doric-Qt/example/doric/doric.pro
@@ -41,6 +41,7 @@ SOURCES += \
         plugin/DoricPopoverPlugin.cpp \
         plugin/DoricShaderPlugin.cpp \
         plugin/DoricStoragePlugin.cpp \
+        shader/DoricDraggableNode.cpp \
         shader/DoricGroupNode.cpp \
         shader/DoricHLayoutNode.cpp \
         shader/DoricImageNode.cpp \
@@ -124,6 +125,7 @@ HEADERS += \
     plugin/DoricPopoverPlugin.h \
     plugin/DoricShaderPlugin.h \
     plugin/DoricStoragePlugin.h \
+    shader/DoricDraggableNode.h \
     shader/DoricGroupNode.h \
     shader/DoricHLayoutNode.h \
     shader/DoricImageNode.h \
diff --git a/doric-Qt/example/doric/resources/draggable.qml b/doric-Qt/example/doric/resources/draggable.qml
new file mode 100644
index 00000000..7c8af7aa
--- /dev/null
+++ b/doric-Qt/example/doric/resources/draggable.qml
@@ -0,0 +1,181 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.5
+import QtQuick.Layouts 1.15
+import QtGraphicalEffects 1.12
+
+import "util.mjs" as Util
+
+Rectangle {
+    id: root
+    property var wrapper
+
+    clip: true
+
+    property var uuid: Util.uuidv4()
+
+    property var tag: "Draggable"
+
+    onWidthChanged: {
+        console.log(tag, uuid + " onWidthChanged: " + this.width)
+
+        updateGradient()
+    }
+
+    onHeightChanged: {
+        console.log(tag, uuid + " onHeightChanged: " + this.height)
+
+        updateGradient()
+    }
+
+    color: 'transparent'
+
+    property var backgroundColor
+
+    onBackgroundColorChanged: {
+        color = backgroundColor
+    }
+
+    property var borderWidth: 0
+    onBorderWidthChanged: {
+        border.width = borderWidth
+    }
+
+    property var borderColor: ""
+    onBorderColorChanged: {
+        border.color = borderColor
+    }
+
+    Drag.active: dragArea.drag.active
+
+    MouseArea {
+        id: dragArea
+        anchors.fill: parent
+
+        drag.target: parent
+    }
+
+    property var shadowColor
+    property var shadowRadius
+    property var shadowOffsetX
+    property var shadowOffsetY
+    property var shadowOpacity
+
+    onShadowOpacityChanged: {
+        if (shadowOpacity > 0) {
+            layer.enabled = true
+        } else {
+            layer.enabled = false
+        }
+    }
+
+    layer.enabled: false
+    layer.effect: DropShadow {
+        horizontalOffset: shadowOffsetX
+        verticalOffset: shadowOffsetY
+        radius: shadowRadius
+        samples: 16
+        color: shadowColor
+        transparentBorder: true
+    }
+
+
+    property var backgroundColorIsObject: false
+    onBackgroundColorIsObjectChanged: {
+        if (backgroundColorIsObject) {
+            lineGradient.anchors.fill = root
+        } else {
+            lineGradient.anchors.fill = null
+        }
+    }
+
+    property variant gradientColors: []
+    property variant gradientLocations: []
+
+    onGradientColorsChanged: {
+        console.log(tag, uuid + " onGradientColorsChanged: " + gradientColors)
+        if (gradientColors.length > 0) {
+            let stops = []
+
+            if (gradientLocations.length == 0) {
+                let unit = 1 / (gradientColors.length - 1)
+                for (let i = 0;i !== gradientColors.length;i++) {
+                    let a = ((gradientColors[i] >> 24) & 0xff) / 255;
+                    let r = ((gradientColors[i] >> 16) & 0xff) / 255;
+                    let g = ((gradientColors[i] >> 8) & 0xff) / 255;
+                    let b = ((gradientColors[i] >> 0) & 0xff) / 255;
+                    let stop = stopComponent.createObject(root, {"position": unit * i, "color": Qt.rgba(r, g, b, a)})
+                    console.log(tag, uuid + " onGradientColorsChanged: " + "position: " + unit * i + " color: " + Qt.rgba(r, g, b, a))
+                    stops.push(stop)
+                }
+            } else {
+                for (let i = 0;i !== gradientColors.length;i++) {
+                    let a = ((gradientColors[i] >> 24) & 0xff) / 255;
+                    let r = ((gradientColors[i] >> 16) & 0xff) / 255;
+                    let g = ((gradientColors[i] >> 8) & 0xff) / 255;
+                    let b = ((gradientColors[i] >> 0) & 0xff) / 255;
+                    let stop = stopComponent.createObject(root, {"position": gradientLocations[i], "color": Qt.rgba(r, g, b, a)})
+                    console.log(tag, uuid + " onGradientColorsChanged: " + "position: " + gradientLocations[i] + " color: " + Qt.rgba(r, g, b, a))
+                    stops.push(stop)
+                }
+            }
+
+            innerGradient.stops = stops
+        }
+    }
+
+    property var orientation: 0
+
+    function updateGradient() {
+        switch (orientation) {
+        case 0:
+            lineGradient.start = Qt.point(0, 0)
+            lineGradient.end = Qt.point(0, root.height)
+            break
+        case 1:
+            lineGradient.start = Qt.point(root.width, 0)
+            lineGradient.end = Qt.point(0, root.height)
+            break
+        case 2:
+            lineGradient.start = Qt.point(root.width, 0)
+            lineGradient.end = Qt.point(0, 0)
+            break
+        case 3:
+            lineGradient.start = Qt.point(root.width, root.height)
+            lineGradient.end = Qt.point(0, 0)
+            break
+        case 4:
+            lineGradient.start = Qt.point(0, root.height)
+            lineGradient.end = Qt.point(0, 0)
+            break
+        case 5:
+            lineGradient.start = Qt.point(0, root.height)
+            lineGradient.end = Qt.point(root.width, 0)
+            break
+        case 6:
+            lineGradient.start = Qt.point(0, 0)
+            lineGradient.end = Qt.point(root.width, 0)
+            break
+        case 7:
+            lineGradient.start = Qt.point(0, 0)
+            lineGradient.end = Qt.point(root.width, root.height)
+            break
+        }
+    }
+    onOrientationChanged: {
+        console.log(tag, uuid + " onOrientationChanged: " + orientation)
+
+        updateGradient()
+    }
+
+    LinearGradient {
+        Component {
+            id:stopComponent
+            GradientStop {}
+        }
+
+        id: lineGradient
+        gradient: Gradient {
+            id: innerGradient
+        }
+    }
+}
diff --git a/doric-Qt/example/doric/shader/DoricDraggableNode.cpp b/doric-Qt/example/doric/shader/DoricDraggableNode.cpp
new file mode 100644
index 00000000..30888365
--- /dev/null
+++ b/doric-Qt/example/doric/shader/DoricDraggableNode.cpp
@@ -0,0 +1,27 @@
+#include "DoricDraggableNode.h"
+
+QQuickItem *DoricDraggableNode::build() {
+  QQmlComponent component(getContext()->getQmlEngine());
+
+  const QUrl url(QStringLiteral("qrc:/doric/qml/draggable.qml"));
+  component.loadUrl(url);
+
+  if (component.isError()) {
+    qCritical() << component.errorString();
+  }
+
+  QQuickItem *item = qobject_cast(component.create());
+  this->createLayouts(item);
+
+  item->setProperty("wrapper", QString::number((qint64)this));
+  return item;
+}
+
+void DoricDraggableNode::blend(QQuickItem *view, QString name,
+                               QJsonValue prop) {
+  if (name == "onDrag") {
+    onDrag = prop.toString();
+  } else {
+    DoricStackNode::blend(view, name, prop);
+  }
+}
diff --git a/doric-Qt/example/doric/shader/DoricDraggableNode.h b/doric-Qt/example/doric/shader/DoricDraggableNode.h
new file mode 100644
index 00000000..5cd810e5
--- /dev/null
+++ b/doric-Qt/example/doric/shader/DoricDraggableNode.h
@@ -0,0 +1,21 @@
+#ifndef DORICDRAGGABLENODE_H
+#define DORICDRAGGABLENODE_H
+
+#include "DoricExport.h"
+
+#include "shader/DoricStackNode.h"
+
+class DORIC_EXPORT DoricDraggableNode : public DoricStackNode {
+
+private:
+  QString onDrag;
+
+public:
+  using DoricStackNode::DoricStackNode;
+
+  QQuickItem *build() override;
+
+  virtual void blend(QQuickItem *view, QString name, QJsonValue prop) override;
+};
+
+#endif // DORICDRAGGABLENODE_H